<?php
/*
    Dill is a tool for creating websites with PHP.
    Copyright (C) 2014  Jannik Haberbosch

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

//
// PHP Extensions
// 

/* The runkit extension has to be included, because some functions may be redefined
during runtime. */
dl( "php_runkit.dll" );


//
// PHP Files
//

// Include core definitions and constants.
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			"constants",
			"core.php"
		)
	)
);

// Load the Dill configuration.
$dill_config = json_decode(
	file_get_contents(
		implode(
			DIRECTORY_SEPARATOR,
			array(
				DILLROOT,
				"dill",
				"config",
				"dill.config"
			)
		)
	),
	TRUE
);

// Load the English language file.
if( strcmp( $dill_config["dill_lang"], "en" ) == 0 )
{
	$langfile = LANG_EN;
}
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			"constants",
			$langfile
		)
	)
);

// Include the PHP module that provides array utitlies/functions.
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"modules",
			"array_utils.php"
		)
	)
);

// Include the PHP module that provides filesystem utilities/functions.
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"modules",
			"filesystem_utils.php"
		)
	)

);
// Include the PHP module that provides logging utilities/functions.
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"modules",
			"logging_utils.php"
		)
	)
);

// Include the PHP module that provides string utilities/functions.
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"modules",
			"string_utils.php"
		)
	)
);

// Include the PHP module that provides Dill utilities/functions.
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"modules",
			"dill_utils.php"
		)
	)
);

// Include the PHP module that provides Dill database utilities/functions
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"modules",
			"dill_sqlite_utils.php"
		)
	)
);

// Include the class mywxTreeCtrl:
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"mywxTreeCtrl.php"
		)
	)
);

// Include the class WebsiteProjectElement
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"WebsiteProjectElement.php"
		)
	)
);

// Include the class WebsiteProjectDatabaseElement
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"WebsiteProjectDatabaseElement.php"
		)
	)
);

// Include the class WebsiteProjectFileElement
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"WebsiteProjectFileElement.php"
		)
	)
);

// Include the class WebsiteProjectJSFile
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"WebsiteProjectJSFile.php"
		)
	)
);

// Include the class WebsiteProjectCSSFile
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"WebsiteProjectCSSFile.php"
		)
	)
);

// Include the class WebsiteProjectModule
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"WebsiteProjectModule.php"
		)
	)
);

// Include the class WebsiteProjectTemplate
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"WebsiteProjectTemplate.php"
		)
	)
);

// Include the class WebsiteProjectContainer
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"WebsiteProjectContainer.php"
		)
	)
);

// Include the class WebsiteProjectPage
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"WebsiteProjectPage.php"
		)
	)
);

// Include the class SimpleSQLiteQuery
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"SimpleSQLiteQuery.php"
		)
	)
);

// Include the class WebsiteProject
require_once(
	implode(
		DIRECTORY_SEPARATOR,
		array(
			DILLROOT,
			"dill",
			"classes",
			"WebsiteProject.php"
		)
	)
);


//
// Set static class variables which are required for each WebsiteProject by default.
//
WebsiteProjectJSFile::set_directory( RELPATH_WEBSITE_JS );
WebsiteProjectCSSFile::set_directory( RELPATH_WEBSITE_CSS );
WebsiteProjectModule::set_directory( RELPATH_MODULES );
WebsiteProjectTemplate::set_directory( RELPATH_TEMPLATES );


//
// Variables, which ought to be used in Dill itself.
//

/* Now follows a definition of globally available variables, that may assist the
website developer when creating a website with Dill.  These variables can be
used within templates and modules to help the user build a website navigation,
for example.
Please take note that these variables will be set to their respective values
as soon as a website project is either openend or created. */

/* $CWS will contain the entire (simplified) website structure, so that a website
navigation may be generated with ease. (Current website structure) */
$CWS = NULL;

/* $ABSPATH_CWP will define the absolute path to the current website project
directory. */
$ABSPATH_CWP = NULL;

/* $ABSPATH_CWP_IN will define the absolute path to the current website project
in directory. */
$ABSPATH_CWP_IN = NULL;

/* $ABSPATH_CWP_OUT will define the absolute path to the current website project
out directory. */
$ABSPATH_CWP_OUT = NULL;

/* $ABSPATH_CWP_OUT_CSS will define the absolute path to the current website project
out css directory. */
$ABSPATH_CWP_OUT_CSS = NULL;

/* $ABSPATH_CWP_OUT_JS will define the absolute path to the current website project
out js directory. */
$ABSPATH_CWP_OUT_JS  = NULL;

/* $ABSPATH_CWP_OUT_MEDIA will define the absolute path to the current website project
out media directory. */
$ABSPATH_CWP_OUT_MEDIA = NULL;

/* $ABSPATH_CWP_OUT_DOWNLOADS will define the absolute path to the current website project
out downloads directory. */
$ABSPATH_CWP_OUT_DOWNLOADS = NULL;

$CURRENT_PAGE_ID = NULL;


//
// GUI
//

/* Now follows the definition of the class GUI, which essentially is responsible
for the user interface (UI) and the handling of the entire application.  One
could say that this is the heart of the application. */
class GUI extends wxFrame
{
	//
	// Private properties
	//

	/* The property "$website_project" will, as soon as a website project is
	either opened or created, be set to the website project's name.
	It is again set to NULL as soon as a website project is closed. */
	private $website_project = NULL;

	/* Actually this property is not used anywhere throughout the program.  It
	will be deleted after a second check and a stability run of Dill has been
	performed and no further reference to the property has been found.
	I will mark this position. */
	private $current_file = NULL; // FIXME - check if can be removed.

	/* This property contains a list of names (strings).  Each of these names
	denote the name of an existing website project.  Names to this array will
	be added as soon as a new project has been created.
	Existing project names will be added to this array as soon as Dill is
	started. */
	private $website_projects_list = array();

	/* This property will later contain the name of the template, which has been
	selected in the wxListBox widget in the wxDialog for managing templates.
	It is reset as soon as the currently opened project is closed. */
	private $chosen_template_in_wxdialog_manage_templates = NULL;

	/* This property will later contain the name of the module, which has been
	selected in the wxListBox widget in the wxDialog widget for managing
	modules.
	It is unset as soon as the currently opened project is closed. */
	private $chosen_module_in_wxdialog_manage_modules = NULL;

	/* This property will later contain the name of the javascript file, that
	has been selected in the wxListBox widget, which is contained in the
	wxDialog widget for managing javascript files.
	The property is set to NULL again as soon as the currently opened website
	project is closed. */
	private $chosen_javascript_in_wxdialog_manage_javascript = NULL;

	/* This property will later contain the name of the css item, that has been
	selected in the wxListBox widget which is contained in the wxDialog widget
	for managing css files.
	This property is set to NULL as soon as the currently opened website project
	is closed. */
	private $chosen_css_in_wxdialog_manage_css = NULL;

	/* This property will later contain the name of the item, which has been
	selected in the wxTreeCtrl widget, which is contained in the wxDialog
	widget for managing the structure of the currently opened website project.
	It is set to NULL as soon as the currently opened website project is closed
	again. */
	private $chosen_item_in_wxdialog_manage_website_structure = NULL;

	/* This property will later, as soon as a website project is either opened,
	or a new one created, be set to an instance of the SQLite3 class.  It thus
	represents an opened connection to the database of the website project.
	This database is created when the website project is set up.
	As soon as an opened website project is closed again, this property will be
	set to NULL. */
	private $db = NULL;

	/* This property will later contain the ID (integer) of the item, that has
	been selected in the wxTreeCtrl widget of the wxDialog widget to manage the
	structure of a website project.
	This property will be set to NULL as soon as an opened website project is
	closed. */
	private $wxtreectrl_manage_website_structure_chosen_item_id = NULL;

	/* This property will later contain information about all the templates,
	which are available in an opened website project.  Each of the items is an
	array itself, which is defined as follows:
	array(
		"template_name" => "",
		"page_containers" => array(),
		"function_containers" => array()
	)
	"page_containers" and "function_containers" will later contain the names of
	the "page -and function containers" respectively.
	This property will be set to NULL as soon as an opened website project is
	set closed. */
	private $current_project_templates = array();

	/* This property will later contain the name of the file that is currently
	being edited in the editor of Dill. TODO: Expand on that.  Verify. */
	private $current_website_project_selected_file = NULL;

	/* This property will later either be set to FALSE or TRUE, depending on
	whether the user is editing a template file or not.
	It will be set to NULL if an opened website project is closed again.
	TODO: Actually, this property might not be needed anymore at all.  Need to
	do a further check later on. */
	private $current_website_project_editing_a_template_file = NULL;

	/* This property will later be set to one of the following constants,
	depending on what is currently being edited in the editor of the main
	window:
		EDITING_CONTAINER
		EDITING_TEMPLATE
		EDITING_MODULE
		EDITING_JS
		EDITING_CSS
	*/
	private $current_website_project_editing_what = NULL;


	//
	// Public functions
	//
	
	function refresh_list_of_website_projects()
	{
		/* Refreshes the array that contains the names of all available website
		projects, and additionally disables or enables the menu item of the main
		menu bar, depending on whether any projects exist.  If no projects do
		yet exist, the menu item to open an existing one is disabled.

		In case of an error, the function calls another function to quit Dill.

		Parameters		Void
		Return values	Void

		*/
		// Returns an array containing the website project directory names.
		// On failure, an error message is shown and Dill quits.
		$this->website_projects_list = get_dirnames(
			ABSPATH_WEBSITE_PROJECTS
		);
		if( $this->website_projects_list === FALSE )
		{
			$this->show_error_dialog(
				ERROR_WEBSITE_PROJECTS_RETRIEVE  . " " . TEXT_EXITING_DILL
			);
			$this->on_menu_main_window_file_exit();
		}

		// Either enable or disable the menu item to open an existing project.
		if( count( $this->website_projects_list ) > 0 && $this->website_project == NULL )
		{
			// At least one website project exists.
			// Enable the menu item to open it.
			$this->menu_main_window_file->Enable(
				WXID_MENU_MAIN_WINDOW_FILE_OPEN_PROJECT,
				TRUE
			);			
		}
		else
		{
			// No website projects exist.
			// Disable the menu item used to open them.
			$this->menu_main_window_file->Enable(
				WXID_MENU_MAIN_WINDOW_FILE_OPEN_PROJECT,
				FALSE
			);
		}
	}

	
	function show_error_dialog( $message )
	{
		/* Creates and shows a wxMessageDialog instance with a user defined
		message that is passed to it as a parameter.
		The wxMessageDialog is shown until the user closes the dialog.

		Parameters		$message
						string
						The message to show to the user.

		Return values	None
		
		*/
		$wxmessagedialog_error = new wxMessageDialog(
			$this,
			$message,
			WXMESSAGE_DIALOG_ERROR_CAPTION
		);
		$wxmessagedialog_error->ShowModal();
	}

	
	function on_menu_main_window_file_exit()
	{
		/* This function destroys the main window and thus, the application is
		terminated. */
		if( isset( $this->wp ) )
		{
			$this->wp->managing_media_client_data = NULL;
		}
		$this->Destroy();
	}


	function on_menu_main_window_file_new_project()
	{
		/* Handles the entire process of setting up a new website project, so
		the user can work on it straight away.

		First of all, a dialog is shown, which prompts the user to enter a valid
		name for the website project he/she wishes to create.  The dialog has
		two buttons, "Ok" and "Cancel".
		A click on "Cancel" immediately returns from the function without creating
		any website project.
		A click on "Ok" is followed by a validation of the project name, which
		the user has entered.  If the validation doesn't pass, a wxMessageDialog
		is shown to the user, after which the function simply returns.
		Otherwise it is checked whether a website project with exactly the same
		name already exists.  If that check fails, a wxMessageDialog is shown,
		after which the function returns aswell.

		After these tests pass, Dill tries to set up the website project.  This
		includes creation directories, files, the database and such.
		On failure, an Exception is thrown, which is caught immediately and
		displayed in a new wxMessageDialog widget.  The function returns.

		On success, Dill tries to establish a connection to the just created
		SQLite3 database.  On failure, and exception is thrown, a wxMessageDialog
		widget is shown, and afterwards, the function simply returns.

		After this task was successful, another function is called that does
		everything that needs to be done once a website project has been opened.

		Parameters		None
		Return values	Void or FALSE
						FALSE is returned on failure.
		
		*/
		/* The user can enter a website project name through a wxTextEntryDialog
		widget. */
		$wxtextentrydialog_new_project = new wxTextEntryDialog(
			$this,
			TEXT_WXTEXTENTRYDIALOG_NEW_PROJECT,
			CAPTION_WXTEXTENTRYDIALOG_NEW_PROJECT,
			wxEmptyString
		);

		/* Show the dialog and execute the body of the if statement if the user
		pressed the "Ok" button. */
		if( $wxtextentrydialog_new_project->ShowModal() == wxID_OK )
		{
			// Make sure that the user has typed in a valid website project name.
			$proposed_website_project_name = $wxtextentrydialog_new_project->GetValue();
			if( preg_match( REGEX_DIRECTORY_NAME, $proposed_website_project_name ) == 1 )
			{
				// Verify that the same website project does not already exist.
				if( !file_exists( makepath( ABSPATH_WEBSITE_PROJECTS,
					$proposed_website_project_name ) ) )
				{
					// Attempt to set up the website project.
					try
					{
						$this->wp = WebsiteProject::create(
							$proposed_website_project_name
						);
					}
					catch( Exception $e )
					{
						$this->show_error_dialog(
							$e->getMessage()
						);
						return FALSE;
					}
					// Refresh the controls in the main window.
					/* Disable and enable certain menu items in the menu bar of
					the main window. */
					$this->on_website_project_opened();
				}
				else
				{
					// A website project with the same name already exists.
					$this->show_error_dialog(
						sprintf(
							ERROR_WEBSITE_PROJECT_DIRECTORY_ALREADY_EXISTS,
							$proposed_website_project_name
						)
					);
					return FALSE;
				}
			}
			else
			{
				// The user has typed in an invalid name for a website project.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_DIRECTORY_NAME,
						$proposed_website_project_name
					)
				);
				return FALSE;
			}
		}
	}
	

	function on_menu_main_window_file_open_project()
	{
		/* Handles the entire sequence of choosing an existing website project
		to open up to opening it actually.

		First, a wxSingleChoiceDialog widget is created, which prompts the user
		to select an existing website project from the choices it offers.  If
		the user chooses to click "Cancel", nothing happens and the function
		simply returns.

		Otherwise Dill tries to open the chosen website project.  This includes
		checking the website project's directory if all required files and
		directories are still there aswell as actually opening the project it-
		self (trying to establish a connection to the SQLite3 database of the
		project).

		If the website project has successfully been opened, further action is
		taken to load it in Dill.

		Parameters		None
		Return values	Void or FALSE
						FALSE is returned on failure.

		*/
		/* Create a dialog from which the user can choose a website project to
		open. */
		$wxsinglechoicedialog_open_project = new wxSingleChoiceDialog(
			$this,
			TEXT_WXSINGLECHOICEDIALOG_OPEN_PROJECT,
			CAPTION_WXSINGLECHOICEDIALOG_OPEN_PROJECT,
			$this->website_projects_list
		);

		/* Show the dialog and enter the body of the if statement, if the user
		clicked the "Ok" button. */
		if( $wxsinglechoicedialog_open_project->ShowModal() == wxID_OK )
		{
			// Store the name of the website project which the user wants to open.
			$selected_project = $wxsinglechoicedialog_open_project->GetStringSelection();

			try
			{
				$this->wp = WebsiteProject::load( $selected_project );
			}
			catch( Exception $e )
			{
				$this->show_error_dialog(
					$e->getMessage()
				);
				return FALSE;
			}

			// Disable certain menu items and load data into controls.
			$this->on_website_project_opened();
		}		
	}


	function on_menu_main_window_project_manage_templates()
	{
		/* Shows a dialog for managing templates (adding, renaming and deleting
		templates).  Before the dialog is shown, all available templates are
		first set in the wxListBox for managing templates, which is part of the
		dialog itself.

		Parameters		Void
		Return values	Void

		*/
		$this->wxlistbox_manage_templates_refresh_list();
		$this->wxdialog_manage_templates->ShowModal();
	}


	function on_wxbutton_manage_templates_add_template_button_click( $event )
	{
		/* Handles adding a new template.

		First, a new wxTextEntryDialog is created, through which the user can
		define the name of the new template to create.

		This dialog is then shown, so that the user may enter a name for the new
		template to create.  If the user presses "Cancel", the function returns
		without doing anything.

		Otherwise, this function calls another function that handles the entire
		process of validating the name, creating the template and so on.  A new
		array that contains information about the template is added to the
		property "$current_project_templates", if TRUE is returned.

		Lastly, the list of templates both in the main window and in the parent
		dialog for managing templates are refreshed, so that the user may either
		rename or delete those items.

		Parameters		None
		Return values	Void or FALSE
						Returns FALSE on failure.

		*/
		// A new template can be created by giving it a name.
		$wxtextentrydialog_add_template = new wxTextEntryDialog(
			$this->wxdialog_manage_templates,
			TEXT_WXTEXTENTRYDIALOG_ADD_TEMPLATES,
			CAPTION_WXTEXTENTRYDIALOG_ADD_TEMPLATES
		);
		
		// Show the dialog and wait until the user has either clicked "Ok" or "Cancel".
		if( $wxtextentrydialog_add_template->ShowModal() == wxID_OK )
		{
			// The user has pressed the "Ok" button.
			$user_input = $wxtextentrydialog_add_template->GetValue();
						
			// Input must match a pattern:
			if( preg_match( REGEX_FILE_NAME, $user_input ) == 0 )
			{
				// Error:  The filename is invalid.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_FILE_NAME,
						$user_input
					)
				);
				return FALSE;
			}

			// A file with the same name must not yet exist in the same directory.
			if( array_key_exists(
				$user_input,
				$this->wp->get_elements(
					WEBSITE_PROJECT_TEMPLATE_FILES
				)
			))
			{
				// Error:  A file with the same filename already exists.
				$this->show_error_dialog(
					sprintf(
						ERROR_WEBSITE_PROJECT_FILE_ALREADY_EXISTS,
						$user_input
					)
				);
				return FALSE;			
			}
			
			// Try to create the file.
			try
			{
				$this->wp->add_element( new WebsiteProjectTemplate( $user_input ) );
			}
			catch( Exception $e )
			{
				$this->show_error_dialog(
					$e->getMessage()
				);
				return FALSE;
			}

			$this->main_window_wxlistbox_templates_refresh_list();
			$this->wxlistbox_manage_templates_refresh_list();

			// Enable the menu item to alter the website structure.
			if( count( $this->wp->get_elements( WEBSITE_PROJECT_TEMPLATE_FILES ) ) == 1 )
			{
				$this->menu_main_window_project->Enable(
					WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_WEBSITE_STRUCTURE,
					TRUE
				);
			}
			
			return TRUE;
		}
	}


	function on_wxbutton_manage_templates_rename_template_button_click()
	{
		/* Handles the entire process of renaming an existing template and
		updating relevant widgets.

		Parameters		None
		Return values	Void or FALSE
						FALSE is returned if an error has occured.

		*/
		// Give the user an ability to rename the template:
		$wxtextentrydialog_manage_templates_rename_template = new wxTextEntryDialog(
			$this,
			TEXT_WXTEXTENTRYDIALOG_MANAGE_TEMPLATES_RENAME_TEMPLATE,
			CAPTION_WXTEXTENTRYDIALOG_MANAGE_TEMPLATES_RENAME_TEMPLATE,
			$this->chosen_template_in_wxdialog_manage_templates
		);

		/* Show the dialog to the user and wait until either "Ok" or "Cancel"
		has been pressed. */
		if( $wxtextentrydialog_manage_templates_rename_template->ShowModal() == wxID_OK )
		{
			// The "Ok" button was clicked.
			$user_input = $wxtextentrydialog_manage_templates_rename_template->GetValue();

			$oldpath = $this->wp->get_elements( WEBSITE_PROJECT_TEMPLATE_FILES )[$this->chosen_template_in_wxdialog_manage_templates]->get_abspath_file();
			$newpath = makepath( WebsiteProjectTemplate::get_abspath_directory(), $user_input );			

			if( preg_match( REGEX_FILE_NAME, $user_input ) == 0 )
			{
				// Error:  Invalid user input.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_FILE_NAME,
						$user_input
					)
				);
				return FALSE;
			}
		
			// A file with the same name must not already exist.
			if( file_exists( $newpath ) )
			{
				// Error:  A file with the same filename already exists.
				$this->show_error_dialog(
					sprintf(
						ERROR_WEBSITE_PROJECT_FILE_ALREADY_EXISTS,
						$this->chosen_template_in_wxdialog_manage_templates
					)
				);
				return FALSE;
			}

			// Try to rename the file now.
			if( !rename( $oldpath, $newpath ) )
			{
				// Error:  The file could not be renamed.
				$this->show_error_dialog(
					sprintf(
						ERROR_RENAME_FILE,
						$this->chosen_template_in_wxdialog_manage_templates,
						$user_input
					)
				);
				return FALSE;			
			}
			else
			{
				// Updating a few object properties related to the new filename.
				$element = $this->wp->get_elements( WEBSITE_PROJECT_TEMPLATE_FILE )[$this->chosen_template_in_wxdialog_manage_templates];
				$element->update_file_related_properties( $user_input );

				// Updating the related array.
				$this->wp->set_elements(
					array_diff_key(
						$this->wp->get_elements(
							WEBSITE_PROJECT_TEMPLATE_FILES
						),
						array( $this->chosen_template_in_wxdialog_manage_templates => "" )
					),
					WEBSITE_PROJECT_TEMPLATE_FILES
				);
				$this->wp->add_element( $element );


				foreach( $this->wp->get( "website_project_pages" ) as $value )
				{
					if( strcmp( $value->get( "template" ), $this->chosen_template_in_wxdialog_manage_templates ) == 0 )
					{
						$this->wp->rename_template_of_page(
							$value->get( "id" ),
							$user_input
						);					
					}
				}

				$this->wp->recreate_website_structure();
				$this->wxdialog_manage_website_structure_wxtreectrl_manage_website_structure_create_website_tree();				
				
				
				// Make the changes visible in both wxListBox widgets.
				$this->main_window_wxlistbox_templates_refresh_list();
				$this->wxlistbox_manage_templates_refresh_list();
				
				/* The button to rename a template needs to be disabled after 
				renaming the selected template. */
				$this->wxbutton_manage_templates_rename_template->Disable();
				
				/* The button to delete a template needs to be disabled after
				renaming the selected template. */
				$this->wxbutton_manage_templates_delete_template->Disable();
			}

			return TRUE;
		}
	}


	function on_wxbutton_manage_templates_delete_template_button_click()
	{
		/* Handles the entire process of deleting a template.

		Parameters		Void
		Return values	Void or FALSE
						Returns FALSE on failure.

		*/
		/* Try to delete the selected template in the wxListBox widget of the
		wxDialog widget. */
		$abspath_file_to_delete = $this->wp->get_elements( WEBSITE_PROJECT_TEMPLATE_FILES )[$this->chosen_template_in_wxdialog_manage_templates]->get_abspath_file();
		if( !unlink( $abspath_file_to_delete ) )
		{
			// Error:  The file could not be deleted.
			$this->show_error_dialog(
				sprintf(
					ERROR_DELETE_FILE,
					$this->chosen_template_in_wxdialog_manage_templates
				)
			);
			return FALSE;		
		}

		$this->wp->set_elements(
			array_diff_key(
				$this->wp->get_elements(
					WEBSITE_PROJECT_TEMPLATE_FILES
				),
				array(
					$this->chosen_template_in_wxdialog_manage_templates => ""
				)
			),
			WEBSITE_PROJECT_TEMPLATE_FILES
		);

		$this->wxbutton_manage_templates_delete_template->Disable();
		$this->wxbutton_manage_templates_rename_template->Disable();

		// Disable the menu item to alter the website structure.
		if( count( $this->wp->get_elements( WEBSITE_PROJECT_TEMPLATE_FILES ) ) == 0 )
		{
			$this->menu_main_window_project->Enable(
				WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_WEBSITE_STRUCTURE,
				FALSE
			);
		}		

		$this->main_window_wxlistbox_templates_refresh_list();
		$this->wxlistbox_manage_templates_refresh_list();

		return TRUE;		
	}


	function on_wxlistbox_manage_templates_selection( $event )
	{
		/* Sets '$chosen_template_in_wxdialog_manage_templates' to the name of
		the item that has been selected in the wxListBox control and activates
		the buttons to delete or/and rename the selected template.
		The delete button is only activated if the template is unused.

		Parameters		$event
						wxCommandEvent
						Contains information about command events.
						
		Return values	None

		*/
		$this->chosen_template_in_wxdialog_manage_templates = $event->GetString();

		// The button to rename a template has to be activated aswell.
		if( !$this->wxbutton_manage_templates_rename_template->IsEnabled() )
		{
			$this->wxbutton_manage_templates_rename_template->Enable();
		}

		// Check whether the selected template is used in any of the pages.
		// If so, then do not enable the delete buttons.
		// Otherwise enable it.

		$website_project_pages = $this->wp->get( "website_project_pages" );
		
		foreach( $website_project_pages as $page )
		{
			if( strcmp( $page->get( "template" ), $this->chosen_template_in_wxdialog_manage_templates ) == 0 )
			{
				$this->wxbutton_manage_templates_delete_template->Enable( FALSE );
				return;
			}
		}
		
		
		// Enable the delete button; the selected template isn't used anywhere.
		if( !$this->wxbutton_manage_templates_delete_template->IsEnabled() )
		{
			$this->wxbutton_manage_templates_delete_template->Enable();
		}
	}


	function on_menu_main_window_project_manage_modules()
	{
		/* Shows the predefined wxDialog for managing modules (add, rename and
		delete modules).  Before the dialog is shown, the wxListBox of that
		dialog is refreshed to contain all already available modules.

		Parameters		None
		Return values	None

		*/
		$this->wxlistbox_manage_modules_refresh_list();
		$this->wxdialog_manage_modules->ShowModal();
	}


	function on_wxlistbox_manage_modules_selection( $event )
	{
		/* Sets the value of '$chosen_module_in_wxdialog_manage_modules' to the
		module that has been selected and enables buttons in the wxDialog to
		rename and/or delete the selected module.

		Parameters		$event
						wxCommandEvent
						Contains information about command events.
						
		Return values	None

		*/
		$this->chosen_module_in_wxdialog_manage_modules = $event->GetString();
		
		if( !$this->wxbutton_manage_modules_rename_module->IsEnabled() )
		{
			$this->wxbutton_manage_modules_rename_module->Enable();
		}
		if( !$this->wxbutton_manage_modules_delete_module->IsEnabled() )
		{
			$this->wxbutton_manage_modules_delete_module->Enable();
		}
	}


	function on_wxbutton_manage_modules_add_module_button_click()
	{
		/* Takes care of the entire process of showing a dialog to create a new
		module, adding it and refreshing related controls.

		Parameters		None
		Return values	Void or FALSE
						Return FALSE on failure.

		*/
		$wxtextentrydialog_manage_modules_add_module = new wxTextEntryDialog(
			$this->wxdialog_manage_modules,
			TEXT_WXTEXTENTRYDIALOG_MANAGE_MODULES_ADD_MODULE,
			CAPTION_WXTEXTENTRYDIALOG_MANAGE_MODULES_ADD_MODULE
		);
		if( $wxtextentrydialog_manage_modules_add_module->ShowModal() == wxID_OK )
		{
			// The user has pressed the "Ok" button.
			$user_input = $wxtextentrydialog_manage_modules_add_module->GetValue();
						
			// Input must match a pattern:
			if( preg_match( REGEX_FILE_NAME, $user_input ) == 0 )
			{
				// Error:  The filename is invalid.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_FILE_NAME,
						$user_input
					)
				);
				return FALSE;
			}

			// A file with the same name must not yet exist in the same directory.
			if( array_key_exists(
				$user_input,
				$this->wp->get_elements(
					WEBSITE_PROJECT_MODULE_FILES
				)
			))
			{
				// Error:  A file with the same filename already exists.
				$this->show_error_dialog(
					sprintf(
						ERROR_WEBSITE_PROJECT_FILE_ALREADY_EXISTS,
						$user_input
					)
				);
				return FALSE;			
			}
			
			// Try to create the file.
			try
			{
				$this->wp->add_element( new WebsiteProjectModule( $user_input ) );
			}
			catch( Exception $e )
			{
				$this->show_error_dialog(
					$e->getMessage()
				);
				return FALSE;
			}

			$this->main_window_wxlistbox_modules_refresh_list();
			$this->wxlistbox_manage_modules_refresh_list();

			return TRUE;
		}
	}

	
	function on_wxbutton_manage_modules_rename_module_button_click()
	{
		/* Takes of the entire process of renaming a module.

		First a wxTextEntryDialog widget is created, through which the user can
		define a new name for the selected module.
		Afterwards, the function to rename a file is called.  On success, the
		related wxListBox widgets are refreshed, so that the updated module
		is shown.

		Parameters		None
		Return values	Void or FALSE
						Returns FALSE on failure.

		*/
		$wxtextentrydialog_manage_modules_rename_module = new wxTextEntryDialog(
			$this,
			TEXT_WXTEXTENTRYDIALOG_MANAGE_MODULES_RENAME_MODULE,
			CAPTION_WXTEXTENTRYDIALOG_MANAGE_MODULES_RENAME_MODULE,
			$this->chosen_module_in_wxdialog_manage_modules
		);
		if( $wxtextentrydialog_manage_modules_rename_module->ShowModal() == wxID_OK )
		{

			// The "Ok" button was clicked.
			$user_input = $wxtextentrydialog_manage_modules_rename_module->GetValue();

			$oldpath = $this->wp->get_elements( WEBSITE_PROJECT_MODULE_FILES )[$this->chosen_module_in_wxdialog_manage_modules]->get_abspath_file();
			$newpath = makepath( WebsiteProjectModule::get_abspath_directory(), $user_input );

			if( preg_match( REGEX_FILE_NAME, $user_input ) == 0 )
			{
				// Error:  Invalid user input.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_FILE_NAME,
						$user_input
					)
				);
				return FALSE;
			}
		
			// A file with the same name must not already exist.
			if( file_exists( $newpath ) )
			{
				// Error:  A file with the same filename already exists.
				$this->show_error_dialog(
					sprintf(
						ERROR_WEBSITE_PROJECT_FILE_ALREADY_EXISTS,
						$this->chosen_module_in_wxdialog_manage_modules
					)
				);
				return FALSE;
			}

			// Try to rename the file now.
			if( !rename( $oldpath, $newpath ) )
			{
				// Error:  The file could not be renamed.
				$this->show_error_dialog(
					sprintf(
						ERROR_RENAME_FILE,
						$this->chosen_module_in_wxdialog_manage_modules,
						$user_input
					)
				);
				return FALSE;			
			}
			else
			{
				// Updating a few object properties related to the new filename.
				$element = $this->wp->get_elements( WEBSITE_PROJECT_MODULE_FILE )[$this->chosen_module_in_wxdialog_manage_modules];
				$element->update_file_related_properties( $user_input );

				// Updating the related array.
				$this->wp->set_elements(
					array_diff_key(
						$this->wp->get_elements(
							WEBSITE_PROJECT_MODULE_FILES
						),
						array( $this->chosen_module_in_wxdialog_manage_modules => "" )
					),
					WEBSITE_PROJECT_MODULE_FILES
				);

				$this->wp->add_element( $element );

				/* The button to rename a template needs to be disabled after 
				renaming the selected template. */
				$this->wxbutton_manage_templates_rename_template->Disable();
				
				/* The button to delete a template needs to be disabled after
				renaming the selected template. */
				$this->wxbutton_manage_templates_delete_template->Disable();

				$this->main_window_wxlistbox_modules_refresh_list();
				$this->wxlistbox_manage_modules_refresh_list();				

				return TRUE;
			}
		}
	}

	
	function on_wxbutton_manage_modules_delete_module_button_click()
	{
		/* Handles the deletion of the selected module in the related wxDialog.

		Deactivates the buttons to rename and to delete a module afterwards.

		Parameters		None
		Return values	Void or FALSE
						Returns FALSE on failure.

		*/
		$abspath_file_to_delete = $this->wp->get_elements( WEBSITE_PROJECT_MODULE_FILES )[$this->chosen_module_in_wxdialog_manage_modules]->get_abspath_file();		
		if( !unlink( $abspath_file_to_delete ) )
		{
			// Error:  The file could not be deleted.
			$this->show_error_dialog(
				sprintf(
					ERROR_DELETE_FILE,
					$this->chosen_module_in_wxdialog_manage_modules
				)
			);
			return FALSE;		
		}

		$this->wp->set_elements(
			array_diff_key(
				$this->wp->get_elements(
					WEBSITE_PROJECT_MODULE_FILES
				),
				array(
					$this->chosen_module_in_wxdialog_manage_modules => ""
				)
			),
			WEBSITE_PROJECT_MODULE_FILES
		);

		// The user has to choose a new item before he can rename/delete a module.
		$this->wxbutton_manage_modules_delete_module->Disable();
		$this->wxbutton_manage_modules_rename_module->Disable();

		$this->main_window_wxlistbox_modules_refresh_list();
		$this->wxlistbox_manage_modules_refresh_list();

		return TRUE;
	}


	function on_menu_main_window_project_manage_javascript()
	{
		/* Displays previously defined wxDialog to add, rename and delete
		JavaScript files.

		Before that is actually done, the wxListBox widget of that dialog is
		refreshed first, so it contains all already available JavaScript files.

		Parameters		None
		Return values	None

		*/
		$this->wxlistbox_manage_js_refresh_list();
		$this->wxdialog_manage_javascript->ShowModal();
	}


	function on_wxlistbox_manage_javascript_selection( $event )
	{
		/* Sets a property to the currently selected value of the item (string),
		and enables the buttons to rename and delete the selected javascript file.

		Parameters		$event
						wxCommandEvent
						Contains information about command events.
						
		Return values	None
		
		*/
		$this->chosen_javascript_in_wxdialog_manage_javascript = $event->GetString();

		if( !$this->wxbutton_manage_javascript_rename_javascript->IsEnabled() )
		{
			$this->wxbutton_manage_javascript_rename_javascript->Enable();
		}
		if( !$this->wxbutton_manage_javascript_delete_javascript->IsEnabled() )
		{
			$this->wxbutton_manage_javascript_delete_javascript->Enable();
		}
	}


	function on_wxbutton_manage_javascript_add_javascript_button_click()
	{
		/* Handles the entire process of adding a new JavaScript file.

		First a dialog is created through which the user can enter a name for
		the new JavaScript file.
		If the "Ok" button is clicked, the function calls another function to
		handle creating the file.
		If that functions returns successfully, the related widgets of dill are
		updated accordingly, to display the newly available JavaScript file.

		Parameters		None
		Return values	Void or FALSE
						Returns FALSE on failure.
		
		*/
		$wxtextentrydialog_manage_javascript_add_javascript = new wxTextEntryDialog(
			$this->wxdialog_manage_javascript,
			TEXT_WXTEXTENTRYDIALOG_MANAGE_JAVASCRIPT_ADD_JAVASCRIPT,
			CAPTION_WXTEXTENTRYDIALOG_MANAGE_JAVASCRIPT_ADD_JAVASCRIPT
		);
		if( $wxtextentrydialog_manage_javascript_add_javascript->ShowModal() == wxID_OK )
		{
			// The "Ok" button was clicked.
			$user_input = $wxtextentrydialog_manage_javascript_add_javascript->GetValue();
						
			// Input must match a pattern:
			if( preg_match( REGEX_FILE_NAME, $user_input ) == 0 )
			{
				// Error:  The filename is invalid.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_FILE_NAME,
						$user_input
					)
				);
				return FALSE;
			}

			// A file with the same name must not yet exist in the same directory.
			if( array_key_exists(
				$user_input,
				$this->wp->get_elements(
					WEBSITE_PROJECT_JAVASCRIPT_FILES
				)
			))
			{
				// Error:  A file with the same filename already exists.
				$this->show_error_dialog(
					sprintf(
						ERROR_WEBSITE_PROJECT_FILE_ALREADY_EXISTS,
						$user_input
					)
				);
				return FALSE;			
			}
			
			// Try to create the file.
			try
			{
				$this->wp->add_element( new WebsiteProjectJSFile( $user_input ) );
			}
			catch( Exception $e )
			{
				$this->show_error_dialog(
					$e->getMessage()
				);
				return FALSE;
			}

			$this->main_window_wxlistbox_javascript_refresh_list();
			$this->wxlistbox_manage_js_refresh_list();

			return TRUE;
		}
	}

	
	function on_wxbutton_manage_javascript_rename_javascript_button_click()
	{
		/* Handles the entire process of renaming a selected JavaScript file.

		First a dialog is created through which the user can enter a new name
		for the selected JavaScript file.
		On the click of the "Ok" button, the function calls another function to
		actually rename the requested file.
		If that function returns successfully, the related wxListBox widgets are
		refreshed, so that the user may see the renamed JavaScript file.

		Parameters		None
		Return values	Void or FALSE
						Returns FALSE on failure.

		*/
		$wxtextentrydialog_manage_javascript_rename_javascript = new wxTextEntryDialog(
			$this,
			TEXT_WXTEXTENTRYDIALOG_MANAGE_JAVASCRIPT_RENAME_JAVASCRIPT,
			CAPTION_WXTEXTENTRYDIALOG_MANAGE_JAVASCRIPT_RENAME_JAVASCRIPT,
			$this->chosen_javascript_in_wxdialog_manage_javascript
		);
		if( $wxtextentrydialog_manage_javascript_rename_javascript->ShowModal() == wxID_OK )
		{
			// The "Ok" button was clicked.
			$user_input = $wxtextentrydialog_manage_javascript_rename_javascript->GetValue();

			$oldpath = $this->wp->get_elements( WEBSITE_PROJECT_JAVASCRIPT_FILES )[$this->chosen_javascript_in_wxdialog_manage_javascript]->get_abspath_file();
			$newpath = makepath( WebsiteProjectJSFile::get_abspath_directory(), $user_input );

			if( preg_match( REGEX_FILE_NAME, $user_input ) == 0 )
			{
				// Error:  Invalid user input.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_FILE_NAME,
						$user_input
					)
				);
				return FALSE;
			}
		
			// A file with the same name must not already exist.
			if( file_exists( $newpath ) )
			{
				// Error:  A file with the same filename already exists.
				$this->show_error_dialog(
					sprintf(
						ERROR_WEBSITE_PROJECT_FILE_ALREADY_EXISTS,
						$this->chosen_javascript_in_wxdialog_manage_javascript
					)
				);
				return FALSE;
			}

			// Try to rename the file now.
			if( !rename( $oldpath, $newpath ) )
			{
				// Error:  The file could not be renamed.
				$this->show_error_dialog(
					sprintf(
						ERROR_RENAME_FILE,
						$this->chosen_javascript_in_wxdialog_manage_javascript,
						$user_input
					)
				);
				return FALSE;			
			}
			else
			{
				// Updating a few object properties related to the new filename.
				$element = $this->wp->get_elements( WEBSITE_PROJECT_JAVASCRIPT_FILES )[$this->chosen_javascript_in_wxdialog_manage_javascript];
				$element->update_file_related_properties( $user_input );

				// Updating the related array.
				$this->wp->set_elements(
					array_diff_key(
						$this->wp->get_elements(
							WEBSITE_PROJECT_JAVASCRIPT_FILES
						),
						array( $this->chosen_javascript_in_wxdialog_manage_javascript => "" )
					),
					WEBSITE_PROJECT_JAVASCRIPT_FILES
				);

				$this->wp->add_element( $element );

				// The file itself has been renamed successfully.
				// Make the change appear in the related wxListBox widgets.
				$this->main_window_wxlistbox_javascript_refresh_list();
				$this->wxlistbox_manage_js_refresh_list();

				$this->wxbutton_manage_javascript_delete_javascript->Disable();
				$this->wxbutton_manage_javascript_rename_javascript->Disable();
						
			}
		}
	}

	
	function on_wxbutton_manage_javascript_delete_javascript_button_click()
	{
		/* Handles the deletion of the selected JavaScript file.

		First this function calls another function to actually delete the file.
		On success, the related wxListBox widgest are refreshed, so that the user
		may see that the JavaScript file has successfully been removed.

		In any case, the buttons to rename or delete another JavaScript file
		are deactivated, until the user chooses another item in the wxListBox
		widget.

		Parameters		None
		Return values	Void or FALSE
						Returns FALSE on failure.

		*/
		$abspath_file_to_delete = $this->wp->get_elements( WEBSITE_PROJECT_JAVASCRIPT_FILES )[$this->chosen_javascript_in_wxdialog_manage_javascript]->get_abspath_file();				
		if( !unlink( $abspath_file_to_delete ) )
		{
			// Error:  The file could not be deleted.
			$this->show_error_dialog(
				sprintf(
					ERROR_DELETE_FILE,
					$this->chosen_javascript_in_wxdialog_manage_javascript
				)
			);
			return FALSE;		
		}

		$this->wp->set_elements(
			array_diff_key(
				$this->wp->get_elements(
					WEBSITE_PROJECT_JAVASCRIPT_FILES
				),
				array(
					$this->chosen_javascript_in_wxdialog_manage_javascript => ""
				)
			),
			WEBSITE_PROJECT_JAVASCRIPT_FILES
		);		

		// The user has to select another item to activate these buttons again.
		$this->wxbutton_manage_javascript_delete_javascript->Disable();
		$this->wxbutton_manage_javascript_rename_javascript->Disable();

		$this->main_window_wxlistbox_javascript_refresh_list();
		$this->wxlistbox_manage_js_refresh_list();

		return TRUE;
	}


	function on_menu_main_window_project_manage_css()
	{
		/* Displays the dialog to add, rename and delete CSS files.

		Before that, all currently available css files are loaded into the
		wxListBox widget.

		Parameters		None
		Return values	None

		*/
		$this->wxlistbox_manage_css_refresh_list();
		$this->wxdialog_manage_css->ShowModal();
	}


	function on_wxlistbox_manage_css_selection( $event )
	{
		/* Sets the property value to the selected item in the wxListBox widget
		(string), and enables the buttons to rename and delete a the selected
		css file.

		Parameters		$event
						wxCommandEvent
						Contains information about command events.

		Return values	None

		*/
		$this->chosen_css_in_wxdialog_manage_css = $event->GetString();

		if( !$this->wxbutton_manage_css_rename_css->IsEnabled() )
		{
			$this->wxbutton_manage_css_rename_css->Enable();
		}
		if( !$this->wxbutton_manage_css_delete_css->IsEnabled() )
		{
			$this->wxbutton_manage_css_delete_css->Enable();
		}
	}


	function on_wxbutton_manage_css_add_css_button_click()
	{
		/* Handles the entire sequence of adding a new CSS file.

		First a dialog is created through which the user can enter the name for
		the CSS file to create.
		On a click on "Ok", this function calls another function to handle the
		process of creating the file itself.
		On success, the related wxListBox widgets are updated so that the added
		CSS file is shown in the list.

		Parameters		None
		Return values	Void or FALSE
						Returns FALSE on failure.

		*/
		$wxtextentrydialog_manage_css_add_css = new wxTextEntryDialog(
			$this->wxdialog_manage_css,
			TEXT_WXTEXTENTRYDIALOG_MANAGE_CSS_ADD_CSS,
			CAPTION_WXTEXTENTRYDIALOG_MANAGE_CSS_ADD_CSS
		);
		if( $wxtextentrydialog_manage_css_add_css->ShowModal() == wxID_OK )
		{
			// The "Ok" button was clicked.
			$user_input = $wxtextentrydialog_manage_css_add_css->GetValue();
						
			// Input must match a pattern:
			if( preg_match( REGEX_FILE_NAME, $user_input ) == 0 )
			{
				// Error:  The filename is invalid.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_FILE_NAME,
						$user_input
					)
				);
				return FALSE;
			}

			// A file with the same name must not yet exist in the same directory.
			if( array_key_exists(
				$user_input,
				$this->wp->get_elements(
					WEBSITE_PROJECT_CSS_FILES
				)
			))
			{
				// Error:  A file with the same filename already exists.
				$this->show_error_dialog(
					sprintf(
						ERROR_WEBSITE_PROJECT_FILE_ALREADY_EXISTS,
						$user_input
					)
				);
				return FALSE;			
			}
			
			// Try to create the file.
			try
			{
				$this->wp->add_element( new WebsiteProjectCSSFile( $user_input ) );
			}
			catch( Exception $e )
			{
				$this->show_error_dialog(
					$e->getMessage()
				);
				return FALSE;
			}
			
				// The file has successfully been created.
				// Refresh related widgets.
			$this->main_window_wxlistbox_css_refresh_list();
			$this->wxlistbox_manage_css_refresh_list();

			return TRUE;
		}	
	}


	function on_wxbutton_manage_css_rename_css_button_click()
	{
		/* Handles the entire process of renaming a selected css file.

		First a dialog is created and displayed through which the user can enter
		a new name for the selected css file.
		On a click on "Ok", a function is called that handles the actual file
		operation of renaming the selected css file.
		On success the related wxListBox widgets are updated to display the
		updated name of the css file.

		Parameters		None
		Return values	Void or FALSE
						Returns FALSE on failure.

		*/
		$wxtextentrydialog_manage_css_rename_css = new wxTextEntryDialog(
			$this,
			TEXT_WXTEXTENTRYDIALOG_MANAGE_CSS_RENAME_CSS,
			CAPTION_WXTEXTENTRYDIALOG_MANAGE_CSS_RENAME_CSS,
			$this->chosen_css_in_wxdialog_manage_css
		);
		if( $wxtextentrydialog_manage_css_rename_css->ShowModal() == wxID_OK )
		{
			// The "Ok" button was clicked.
			$user_input = $wxtextentrydialog_manage_css_rename_css->GetValue();

			$oldpath = $this->wp->get_elements( WEBSITE_PROJECT_CSS_FILES )[$this->chosen_css_in_wxdialog_manage_css]->get_abspath_file();
			$newpath = makepath( WebsiteProjectCSSFile::get_abspath_directory(), $user_input );

			if( preg_match( REGEX_FILE_NAME, $user_input ) == 0 )
			{
				// Error:  Invalid user input.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_FILE_NAME,
						$user_input
					)
				);
				return FALSE;
			}
		
			// A file with the same name must not already exist.
			if( file_exists( $newpath ) )
			{
				// Error:  A file with the same filename already exists.
				$this->show_error_dialog(
					sprintf(
						ERROR_WEBSITE_PROJECT_FILE_ALREADY_EXISTS,
						$this->chosen_css_in_wxdialog_manage_css
					)
				);
				return FALSE;
			}

			// Try to rename the file now.
			if( !rename( $oldpath, $newpath ) )
			{
				// Error:  The file could not be renamed.
				$this->show_error_dialog(
					sprintf(
						ERROR_RENAME_FILE,
						$this->chosen_css_in_wxdialog_manage_css,
						$user_input
					)
				);
				return FALSE;			
			}
			else
			{
				// Updating a few object properties related to the new filename.
				$element = $this->wp->get_elements( WEBSITE_PROJECT_CSS_FILES )[$this->chosen_css_in_wxdialog_manage_css];
				$element->update_file_related_properties( $user_input );

				// Updating the related array.
				$this->wp->set_elements(
					array_diff_key(
						$this->wp->get_elements(
							WEBSITE_PROJECT_CSS_FILES
						),
						array( $this->chosen_css_in_wxdialog_manage_css => "" )
					),
					WEBSITE_PROJECT_CSS_FILES
				);

				$this->wp->add_element( $element );
							
				// Refresh related wxListBox widgets.
				$this->main_window_wxlistbox_css_refresh_list();
				$this->wxlistbox_manage_css_refresh_list();

				$this->wxbutton_manage_css_rename_css->Disable();
				$this->wxbutton_manage_css_delete_css->Disable();				

				return TRUE;			
			}
		}		
	}


	function on_wxbutton_manage_css_delete_css_button_click()
	{
		/* Handles the deletion of the selected css file.
		Disables the buttons to rename and delete a css file in any case.

		Parameters		None
		Return values	Void or FALSE
						Returns FALSE on failure.

		*/
		$abspath_file_to_delete = $this->wp->get_elements( WEBSITE_PROJECT_CSS_FILES )[$this->chosen_css_in_wxdialog_manage_css]->get_abspath_file();
		if( !unlink( $abspath_file_to_delete ) )
		{
			// Error:  The file could not be deleted.
			$this->show_error_dialog(
				sprintf(
					ERROR_DELETE_FILE,
					$this->chosen_css_in_wxdialog_manage_css
				)
			);
			return FALSE;		
		}

		$this->wp->set_elements(
			array_diff_key(
				$this->wp->get_elements(
					WEBSITE_PROJECT_CSS_FILES
				),
				array(
					$this->chosen_css_in_wxdialog_manage_css => ""
				)
			),
			WEBSITE_PROJECT_CSS_FILES
		);	

		$this->wxbutton_manage_css_rename_css->Disable();
		$this->wxbutton_manage_css_delete_css->Disable();

		$this->main_window_wxlistbox_css_refresh_list();
		$this->wxlistbox_manage_css_refresh_list();

		return TRUE;
	}


	function on_menu_main_window_project_generatewebsite()
	{
		/* This function generates the website.

		First the entire representation of the structure of the website is
		needed.
		If the website project does have at least one page, the output directory
		"pages" is removed.
		What happens now is that an easy representation of the website structure
		is generated.  This representation is only created to assist the website
		developer generate a website navigation for example.
		Afterwards the modules which the player has created are included.  For
		this task, the "runkit" extension is used, because we need to be able to
		change a function or class during runtime, and not only after the program
		has been restarted.  "require_once" would do no justice.
		Next two absolute paths to the root directory "pages" of the website
		project, and to the templates directory of the website project are
		defined.
		Now any CSS files in the "out" directory of the website project are re-
		moved.  Then the CSS files in the "in" directory of the website project
		are copied into it.
		The same procedure happens to the JavaScript files.
		Then at last another function is called that generates the pages.  After
		this has been done, the generation of the website is finished.

		Parameters		None
		Return values	Void or FALSE
						FALSE is returned in case of an error.
		 
		*/

		// Store a representation of the website structure.
		$website_structure = $this->wp->get_website_structure();

		/* Remove the "website/pages" directory if the website project has at least
		one page. */
		if( count( $website_structure ) > 0 )
		{
			$res = rmtree(
				makepath(
					$this->wp->get_abspath_website_project(),
					RELPATH_WEBSITE_PAGES
				)
			);
			if( $res === FALSE )
			{
				// The directory tree could not be removed.
				$this->show_error_dialog(
					sprintf(
						ERROR_REMOVE_DIRECTORY_TREE,
						RELPATH_WEBSITE_PAGES
					)
				);
				return FALSE;
			}
		}

		/* An easy representation of the website structure is created here.
		This array can be used by the user to create a navigation for the
		website. */
		global $CWS;
		$CWS = make_cws( $website_structure );

		/* All modules which the user has created are included.
		For this taskthe "runkit_import" function of the extension "runkit" is
		used, because the user may change the body of a function during runtime
		of the program, and PHP normally does not allow that.  This extension
		makes it possible. */
		$modules_path = makepath(
			ABSPATH_WEBSITE_PROJECTS,
			$this->website_project,
			RELPATH_MODULES
		);
		foreach( $this->wp->get_elements( WEBSITE_PROJECT_MODULE_FILES ) as $module )
		{
			$res = runkit_import(
				$module->get_abspath_file(),
				RUNKIT_IMPORT_OVERRIDE | RUNKIT_IMPORT_FUNCTIONS
			);
			if( $res === FALSE )
			{
				// Import error.
				$this->show_error_dialog(
					sprintf(
						ERROR_RUNKIT_IMPORT_MODULE,
						$module
					)
				);
				return FALSE;
			}
		}

		// The absolute path to the "out/pages" directory of the website project.
		$root_dir = makepath(
			$this->wp->get_abspath_website_project(),
			RELPATH_WEBSITE_PAGES
		);

		// The absolute path to the "in/templates" directory of a website project.
		$abs_template_path = WebsiteProjectTemplate::get_abspath_directory();
		
		/* Generate the pages (directories and files, that is) inside the direc-
		tory "out/pages". */
		try
		{
			$this->wp->generate_pages( $website_structure, $root_dir, $abs_template_path );
		}
		catch( Exception $e )
		{
			// Error:  An error has occured while trying to generate the website.
			$this->show_error_dialog( $e->getMessage() );
			return FALSE;
		}
	}


	function on_menu_main_window_project_close()
	{
		/* Closes the currently opened website project.

		Disables the "Project" menu, and enables the menuitems "New" and "Open"
		of the "File" menu.

		Almost all properties are set to their default value.
		Items are removed from wxListBox widgets and such.

		Global variables are reset.


		Parameters		None
		Return values	None

		*/
		$this->wxlistbox_manage_css->Clear();
		$this->wxlistbox_manage_javascript->Clear();
		$this->wxlistbox_manage_modules->Clear();
		$this->wxlistbox_manage_templates->Clear();			

		$this->wxlistbox_main_window_css->Clear();
		$this->wxlistbox_main_window_modules->Clear();
		$this->wxlistbox_main_window_templates->Clear();
		$this->wxtextctrl_main_window_editor->ClearAll();
		$this->wxtreectrl_main_window_website_structure->DeleteAllItems(); // FIXME:  BUG???
		$this->wxlistbox_main_window_containers->Clear();
		$this->wxlistbox_main_window_javascript->Clear();		
	

		$this->current_file = NULL;
		$this->chosen_template_in_wxdialog_manage_templates = NULL;
		$this->chosen_module_in_wxdialog_manage_modules = NULL;
		$this->chosen_javascript_in_wxdialog_manage_javascript = NULL;
		$this->chosen_css_in_wxdialog_manage_css = NULL;
		$this->chosen_item_in_wxdialog_manage_website_structure = NULL;
		$this->wxtreectrl_manage_website_structure_chosen_item_id = NULL;
		$this->current_project_templates = array();
		$this->current_website_project_selected_file = NULL;
		$this->current_website_project_editing_a_template_file = NULL;
		$this->current_website_project_editing_what = NULL;
		$this->wxstatictext_main_window_website_structure_template_used->SetLabel(
			"-"
		);
	

		global $CWS;
		$CWS = NULL;
		global $ABSPATH_CWP;
		$ABSPATH_CWP = NULL;
		global $ABSPATH_CWP_IN;		
		$ABSPATH_CWP_IN = NULL;
		global $ABSPATH_CWP_OUT;
		$ABSPATH_CWP_OUT = NULL;
		global $ABSPATH_CWP_OUT_CSS;
		$ABSPATH_CWP_OUT_CSS = NULL;
		global $ABSPATH_CWP_OUT_JS;
		$ABSPATH_CWP_OUT_JS  = NULL;
		global $ABSPATH_CWP_OUT_MEDIA;
		$ABSPATH_CWP_OUT_MEDIA = NULL;
		global $ABSPATH_CWP_OUT_DOWNLOADS;
		$ABSPATH_CWP_OUT_DOWNLOADS = NULL;	

		$this->menubar_main_window->EnableTop( 1, FALSE );
		$this->menu_main_window_file->Enable(
			WXID_MENU_MAIN_WINDOW_FILE_NEW_PROJECT,
			TRUE
		);
	
		$this->menu_main_window_file->Enable(
			WXID_MENU_MAIN_WINDOW_FILE_OPEN_PROJECT,
			TRUE
		);

		$this->wxdataviewtreectrl_main_window_media->DeleteAllItems();
		$this->wxdataviewtreectrl_main_window_downloads->DeleteAllItems();
		$this->wp->managing_media_client_data = NULL;

		$this->website_project = NULL;
		$this->wp->close();
		$this->wp = NULL;	
		
	}


	function on_menu_main_window_help_help()
	{
		/* Displays a dialog or a window with help related to Dill.

		Parameters		None
		Return values	None

		*/
		// TODO:  Implement it.
		echo "HELP";
	}


	function on_menu_main_window_help_about()
	{
		/* Displays a dialog with information about Dill.

		Parameters		None
		Return values	None

		*/
		// TODO:  Implement it.
		echo "ABOUT";
	}


	function create_wxtreectrl_tree( $data, $parentid )
	{
		/* Fills the wxTreeCtrl widget "wxtreectrl_manage_website_structure"
		with items (a tree is generated).

		Parameters		$data
						array
						An array that contains the entire website structure.

						$parentid
						wxTreeCtrlItem
						Represents the previously added item.

		Return values	None

		TODO:
			Rename the function to something a bit more appropriate ?
			
		*/
		foreach( $data as $item )
		{
			$wxtreeitemdata = new wxTreeItemData();
			$resultid = $this->wxtreectrl_manage_website_structure->AppendItem(
				$parentid,
				$item['name']
			);
			if( isset( $item["children"] ) && is_array( $item['children'] ) )
			{
				$this->create_wxtreectrl_tree(
					$item['children'],
					$resultid
				);
			}
		}
	}


	function create_wxtreectrl_tree2( &$wxtreectrl, $data, $parentid )
	{
		/* Fills the passed parameter $wxtreectrl wxTreeCtrl widget with items
		(a tree is generated).

		Parameters		$wxtreectrl
						wxTreeCtrl
						Passed by reference.  This wxTreeCtrl will be filled
						with items that make up the structure of the currently
						opened website project.

						$data
						array
						An array that contains the entire website structure.

						$parentid
						wxTreeeCtrlItem
						Represents the previously added item.

		Return values	None

		TODO:
			Rename the function to something a bit more appropriate ?

		*/
		foreach( $data as $item )
		{
			$resultid = $wxtreectrl->AppendItem(
				$parentid,
				$item['name']
			);
			if( isset( $item["children"] ) && is_array( $item['children'] ) )
			{
				$this->create_wxtreectrl_tree2(
					$wxtreectrl,
					$item['children'],
					$resultid
				);
			}
		}
	}


	function create_website_structure_tree( &$wxtreectrl, $data, $parentid, $ids_to_ignore = array() )
	{
		foreach( $data as $key => $value )
		{
			if( in_array( $value["self"]->get( "id" ), $ids_to_ignore ) ) continue;
			
			$resultid = $wxtreectrl->AppendItem(
				$parentid,
				$key
			);
			if( isset( $value["children"] ) && is_array( $value['children'] ) )
			{
				$this->create_website_structure_tree(
					$wxtreectrl,
					$value['children'],
					$resultid,
					$ids_to_ignore
				);
			}
		}	
	}


	function on_menu_main_window_project_manage_website_structure()
	{
		/* Displays the previously created wxDialog to manage the website
		structure.

		Although before the dialog is displayed, the wxTreeCtrl items are
		deleted, and then reset so that the current website structure is
		displayed accordingly.

		Parameters		None
		Return values	None

		*/
		$this->wxtreectrl_manage_website_structure->DeleteAllItems();
		$this->wxdialog_manage_website_structure_wxtreectrl_manage_website_structure_create_website_tree();
		$this->wxdialog_manage_website_structure->ShowModal();
	}


	function wxdialog_manage_website_structure_wxtreectrl_manage_website_structure_create_website_tree()
	{
		/* This function fills the wxTreeCtrl of the dialog through which the
		user can manage the website structure with items that represent the
		current website stucture of the loaded project.

		Parameters		None
		Return values	Void or FALSE
						On failure FALSE is returned.
		
		*/
		// Delete the old tree first.
		$this->wxtreectrl_manage_website_structure->DeleteAllItems();

		// Retrieve a copy of the website structure.
		$website_structure = $this->wp->get_website_structure();

		// A root node is required for the wxTreeCtrl widget.  It won't be shown.
		$rootid = $this->wxtreectrl_manage_website_structure->AddRoot( "Root" );
		
		// Create the tree now.
		$this->create_website_structure_tree(
			$this->wxtreectrl_manage_website_structure,
			$website_structure,
			$rootid
		);
		

		// All items are visible.
		$this->wxtreectrl_manage_website_structure->ExpandAll();

		// No item can be chosen if all items have been removed.
		if( count( $website_structure ) == 0 )
		{
			$this->chosen_item_in_wxdialog_manage_website_structure = NULL;
		}
	}


	function on_wxtreectrl_manage_website_structure_selection( $event )
	{
		/* The user has clicked on an item.  If the item was selected previously,
		then the item is deselected (right mouse click), and the controls are
		deactivated again.
		Otherwise enable almost all of the other buttons.  If a node has only got
		one item, then the buttons for moving an item up and down are deactivated.
		Otherwise enable all other buttons and store the name of the item that
		has been selected as a string.

		Parameters		$event
						wxTreeEvent
						A tree event holds information about event associated
						with wxTreeCtrl objects.

		Return values	None

		XXX:  Split this function in two parts.
		FIXME:  There is a bug associated with this function.

		*/

		// BUG WORKAROUND
		if( $this->wp == NULL ) return;

		// Always deactivate all buttons except the "Add" button.
		$this->wxbutton_manage_website_structure_rename_item->Enable( FALSE );
		$this->wxbutton_manage_website_structure_delete_item->Enable( FALSE );		
		$this->wxbutton_manage_website_structure_move_up_item->Enable( FALSE );
		$this->wxbutton_manage_website_structure_move_down_item->Enable( FALSE );
		$this->wxbutton_manage_website_structure_relocate_itemtree->Enable( FALSE );
		$this->wxbutton_manage_website_structure_change_template->Enable( FALSE );

		// Store the name of the selected item.
		$selected_item_name = $this->wxtreectrl_manage_website_structure->GetItemText(
			$this->wxtreectrl_manage_website_structure->GetSelection()
		);

		// If the user right-clicked on an already selected item, deselect it.
		if( strcmp( $this->chosen_item_in_wxdialog_manage_website_structure,
			$selected_item_name ) == 0 )
		{
			$this->wxtreectrl_manage_website_structure->Unselect();
			$this->chosen_item_in_wxdialog_manage_website_structure = NULL;

			// Deactivate all except the "Add" button.
			$this->wxbutton_manage_website_structure_rename_item->Enable( FALSE );
			$this->wxbutton_manage_website_structure_delete_item->Enable( FALSE );		
			$this->wxbutton_manage_website_structure_move_up_item->Enable( FALSE );
			$this->wxbutton_manage_website_structure_move_down_item->Enable( FALSE );
			$this->wxbutton_manage_website_structure_relocate_itemtree->Enable( FALSE );
			$this->wxbutton_manage_website_structure_change_template->Enable( FALSE );

			// Set the template which is used for the selected page:
			$this->wxstatictext_manage_website_structure_template_used->SetLabel(
				"-"
			);
		}
		// Otherwise the user has chosen another item (left-click):
		else
		{
			// Store the name of the selected item in the designated property.
			$this->chosen_item_in_wxdialog_manage_website_structure = $selected_item_name;

			/* The selected item can be moved up and down if it has at least one
			sibling. */
			$selected_item = dill_utils_website_structure_get_data_for_selected_item(
				$this->wp->get_website_structure(),
				$this->wxtreectrl_manage_website_structure,
				$this->chosen_item_in_wxdialog_manage_website_structure
			);
			if( $selected_item === FALSE )
			{
				$this->show_error_dialog(
					ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
				);
				return FALSE;
			}

			
			$siblings = $this->wp->get_child_pages( $selected_item->get( "parent_id" ) );
			
			if( count( $siblings ) > 1 )
			{
				/* The selected item has at least one siblings, so it can be
				moved.  Now check whether the selected item can be moved up, down
				or both ways.
				Activate the buttons to do that accordingly. */
				if( $selected_item->get( "sort_id" ) == 1 )
				{
					$this->wxbutton_manage_website_structure_move_down_item->Enable();						
				}
				else if( count( $siblings ) == $selected_item->get( "sort_id" ) )
				{
					$this->wxbutton_manage_website_structure_move_up_item->Enable();				
				}
				else
				{
					$this->wxbutton_manage_website_structure_move_up_item->Enable();
					$this->wxbutton_manage_website_structure_move_down_item->Enable();				
				}
			}

			// Set the template which is used for the selected page:
			$this->wxstatictext_manage_website_structure_template_used->SetLabel(
				$selected_item->get( "template" )
			);

			/* All other relevant buttons to do something with the selected item
			are enabled by default. */
			$this->wxbutton_manage_website_structure_rename_item->Enable();
			$this->wxbutton_manage_website_structure_delete_item->Enable();
			$this->wxbutton_manage_website_structure_relocate_itemtree->Enable();
			$this->wxbutton_manage_website_structure_change_template->Enable();
		}
	}


	function on_wxbutton_manage_website_structure_add_item_clicked()
	{
		/* Creats and displays a dialog to add a new item and handles adding an
		item.

		First an array of all available templates is created.
		
		Next a dialog is created, through which the user can define the name of
		the new page and select a template.

		On a click on the "Ok" button, the function tries to create the new page.
		This includes checking, if the user has typed in a valid name, assigned
		a template and whether an item with the same name exists in the branch,
		where the item should be added to.

		If the page has successfully been created, the related wxTreeCtrl, both
		in the main window and in the window for managing the website structure
		are refreshed to represent the changes made.

		For a detailed description, please read through the body of this
		function.

		Parameters		None
		Return values	Void or FALSE
						FALSE is returned on failure.

		*/

		// An array that contains the names of all available templates.
		$list_of_available_templates = array_keys(
			$this->wp->get_elements(
				WEBSITE_PROJECT_TEMPLATE_FILES
			)
		);

		
		// Create the dialog.
		$wxdialog_manage_website_structure_add_item = new wxDialog(
			$this->wxdialog_manage_website_structure,
			ID_WXDIALOG_MANAGE_WEBSITE_STRUCTURE_ADD_ITEM,
			CAPTION_WXDIALOG_MANAGE_WEBSITE_STRUCTURE_ADD_ITEM
		);

		// We need a panel for our dialog.
		$wxpanel_manage_website_structure_add_item = new wxPanel(
			$wxdialog_manage_website_structure_add_item,
			wxID_ANY
		);

		// Our controls are aligned vertically.
		$wxvbox_manage_website_structure_add_item = new wxBoxSizer(
			wxVERTICAL
		);

		// We need a static text to inform the user to enter a page name.
		$wxstatictext_manage_website_structure_add_item_pagename = new wxStaticText(
			$wxpanel_manage_website_structure_add_item,
			wxID_ANY,
			TEXT_WXSTATICTEXT_MANAGE_WEBSITE_STRUCTURE_ADD_ITEM_PAGENAME
		);
		$wxvbox_manage_website_structure_add_item->Add(
			$wxstatictext_manage_website_structure_add_item_pagename,
			0,
			wxEXPAND
		);

		// We need a wxTextEntry control through which the user can define the name.
		$wxtextctrl_manage_website_structure_add_item_pagename = new wxTextCtrl(
			$wxpanel_manage_website_structure_add_item,
			WXID_WXTEXTCTRL_MANAGE_WEBSITE_STRUCTURE_ADD_ITEM_PAGENAME
		);
		$wxvbox_manage_website_structure_add_item->Add(
			$wxtextctrl_manage_website_structure_add_item_pagename,
			0,
			wxEXPAND
		);

		/* Next we need another static text that informs the user to select a
		template from a list of choices. */
		$wxstatictext_manage_website_structure_add_item_template = new wxStaticText(
			$wxpanel_manage_website_structure_add_item,
			wxID_ANY,
			TEXT_WXSTATICTEXT_MANAGE_WEBSITE_STRUCTURE_ADD_ITEM_TEMPLATE
		);
		$wxvbox_manage_website_structure_add_item->Add(
			$wxstatictext_manage_website_structure_add_item_template,
			0,
			wxEXPAND
		);

		/* And lasty, we need a wxChoice control from which the user can select
		a single template to be used for the new page. */
		$wxchoice_manage_website_structure_add_item_template = new wxChoice(
			$wxpanel_manage_website_structure_add_item,
			WXID_WXCHOICE_MANAGE_WEBSITE_STRUCTURE_ADD_ITEM_TEMPLATE,
			wxDefaultPosition,
			wxDefaultSize,
			$list_of_available_templates,
			wxCB_SORT
		);
		$wxvbox_manage_website_structure_add_item->Add(
			$wxchoice_manage_website_structure_add_item_template,
			0,
			wxEXPAND
		);


		/* Oh, and we need two buttons, both an OK and a CANCEL button.  Those
		will be aligned horizontally. */
		$wxhbox_manage_website_structure_add_item = new wxBoxSizer( wxHORIZONTAL );

		$wxbutton_manage_website_structure_add_item_ok = new wxButton(
			$wxpanel_manage_website_structure_add_item,
			wxID_OK,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_ADD_ITEM_OK
		);
		$wxhbox_manage_website_structure_add_item->Add(
			$wxbutton_manage_website_structure_add_item_ok,
			0,
			wxEXPAND
		);

		$wxbutton_manage_website_structure_add_item_cancel = new wxButton(
			$wxpanel_manage_website_structure_add_item,
			wxID_CANCEL,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_ADD_ITEM_CANCEL
		);
		$wxhbox_manage_website_structure_add_item->Add(
			$wxbutton_manage_website_structure_add_item_cancel,
			0,
			wxEXPAND
		);

		// Add both the vertical and the horizontal box to a new vertical box.
		$wxvbox = new wxBoxSizer( wxVERTICAL );
		$wxvbox->Add(
			$wxvbox_manage_website_structure_add_item,
			0,
			wxEXPAND
		);
		$wxvbox->Add(
			$wxhbox_manage_website_structure_add_item,
			0,
			wxEXPAND
		);

		/* Now we need to make sure that all controls are displayed when the
		dialog is shown. */
		$wxpanel_manage_website_structure_add_item->SetSizer( $wxvbox );
		$wxvbox->SetSizeHints( $wxdialog_manage_website_structure_add_item );		

		/* Show the dialog and execute the body of the if statement on a click
		on the "Ok" button. */
		if( $wxdialog_manage_website_structure_add_item->ShowModal() == wxID_OK )
		{
			// Store what has been entered and chosen by the user.
			$chosen_pagename = $wxtextctrl_manage_website_structure_add_item_pagename->GetValue();
			$selected_template = $wxchoice_manage_website_structure_add_item_template->GetString(
				$wxchoice_manage_website_structure_add_item_template->GetSelection()
			);

			// The pagename must be valid.
			if( preg_match( REGEX_FILE_NAME, $chosen_pagename ) == 0 )
			{
				// The user has typed in an invalid pagename.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_PAGE_NAME,
						$chosen_pagename
					)
				);
				return FALSE;
			}

			// The user has to select a template.
			if( $selected_template == NULL )
			{
				// The user didn't select a template.
				$this->show_error_dialog(
					ERROR_WEBSITE_STRUCTURE_NO_TEMPLATE_CHOSEN
				);
				return FALSE;
			}

			/* Decide whether the user wants to add an item to an existing node,
			or create a parent. */
			if( $this->chosen_item_in_wxdialog_manage_website_structure == NULL )
			{
				// Create a parent page.
				$website_structure = $this->wp->get_website_structure();

				/* Checking if an existing parent node has the same name is not
				required if there are no parent pages yet. */
				if( count( $website_structure ) == 0 )
				{
					// The sort_id 1 is assigned to the first parent page.
					$sort_id = 1;

					// Try to create the page.
					try
					{
						$this->wp->create_page_and_containers( $chosen_pagename, $selected_template, $sort_id );
					}
					catch( Exception $e )
					{
						// The parent page could not be created.
						$this->show_error_dialog( $error_msg ); // FIXME:  $error_msg is not defined anywhere.
						return FALSE;
					}
				}
				else
				{
					/* There is already at least one parent page.  We need to
					make sure that the pagename the user has entered does not
					match an existing pagename. */
					foreach( $website_structure as $ppr )
					{
						if( strcmp(
							$ppr["self"]->get( "name" ),
							$chosen_pagename
						) == 0 )
						{
							// A page with that name already exists.
							$this->show_error_dialog(
								ERROR_PAGE_SAME_NAME_EXISTS
							);
							return FALSE;
						}
					}

					/* By default, an additional parent page is added at the end
					of the parent pages. */
					$sort_id = count( $website_structure ) + 1;
					
					// Try to create the page.
					try
					{
						$this->wp->create_page_and_containers( $chosen_pagename, $selected_template, $sort_id );
					}
					catch( Exception $e )
					{
						// The parent page could not be created.
						$this->show_error_dialog( $e->getMessage() );
					}
				}
			}
			else
			{
				// The user wants to add a page to an existing node.
				/* We need the value of the 'id' column inside the 'page' table
				of the database, that represents the currently selected item. */
				$item_db = dill_utils_website_structure_get_data_for_selected_item(
					$this->wp->get_website_structure(),
					$this->wxtreectrl_manage_website_structure,
					$this->chosen_item_in_wxdialog_manage_website_structure
				);
				if( $item_db === FALSE )
				{
					// Data for the selected item could not be retrieved.
					$this->show_error_dialog(
						ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
					);
					return FALSE;
				}
				
				$item_db_id = $item_db->get( "id" );

				/* Now we need to make sure that the pagename is unique in the 
				current node.  This check is required only if is at least one
				page in the current node. */
				$child_pages = $this->wp->get_child_pages( $item_db_id );
				if( $child_pages === FALSE )
				{
					// Child pages records could not be retrieved.
					$this->show_error_dialog(
						ERROR_RETRIEVE_CHILD_PAGES_RECORDS
					);
					return FALSE;
				}

				/* A comparison is unnecessary if there aren't an child pages in
				the same node. */
				if( count( $child_pages ) == 0 )
				{
					// As it is the first page in the node, it appears at the top.
					$sort_id = 1;

					$this->wp->create_page_and_containers(
						$chosen_pagename,
						$selected_template,
						$sort_id,
						$item_db_id
					);
				}
				else
				{
					/* The user must have typed in a unique name for the page to
					add. */
					foreach( $child_pages as $cpr )
					{
						if( strcmp( $cpr->get( "name" ), $chosen_pagename ) == 0 )
						{
							/* Error: The name which the user has typed in is
							already taken. */
							$this->show_error_dialog(
								sprintf(
									ERROR_PAGENAME_EXISTS_IN_CURRENT_NODE,
									$chosen_pagename
								)
							);
							return FALSE;
						}
					}
										
					// The page will be appended at the end of the node.
					$sort_id = count( $child_pages ) + 1;

					$this->wp->create_page_and_containers(
						$chosen_pagename,
						$selected_template,
						$sort_id,
						$item_db_id
					);				
				}	
			}

			/* Recreate the website structure representation both in the dialog
			for managing the website structure aswell as in the main window. */
			// We've got to reload and recreate the new website structure.
			$this->wp->recreate_website_structure();
			$this->wxdialog_manage_website_structure_wxtreectrl_manage_website_structure_create_website_tree();
			$this->main_window_wxtreectrl_refresh_website_structure();			
		}
	}


	function on_wxbutton_manage_website_structure_rename_item_clicked()
	{
		/* Creates and displays a dialog to rename a selected item in the
		wxTreeCtrl widget plus it also handles renaming the selected item and
		refreshing the related wxTreeCtrl widgets aswell.

		Parameters		None
		Return values	Void or FALSE
						FALSE is returned on failure.

		*/
		$wxtextentrydialog_manage_website_structure_rename_item = new wxTextEntryDialog(
			$this->wxdialog_manage_website_structure,
			TEXT_WXTEXTENTRYDIALOG_MANAGE_WEBSITE_STRUCTURE_RENAME_ITEM,
			CAPTION_WXTEXTENTRYDIALOG_MANAGE_WEBSITE_STRUCTURE_RENAME_ITEM,
			$this->chosen_item_in_wxdialog_manage_website_structure
		);
		// Show the dialog and enter the if body if the "Ok" button has been clicked.
		if( $wxtextentrydialog_manage_website_structure_rename_item->ShowModal() == wxID_OK )
		{
			// Store the user's input in a variable.
			$proposed_item_name = $wxtextentrydialog_manage_website_structure_rename_item->GetValue();
			
			// The user input must be valid.
			if( preg_match( REGEX_FILE_NAME, $proposed_item_name ) == 0 )
			{
				// The input is invalid.
				$this->show_error_dialog(
					sprintf(
						ERROR_INVALID_PAGE_NAME,
						$proposed_item_name
					)
				);
				return FALSE;
			}

			// Try to retreive db data for the selected item in our wxTreeCtrl.
			$selected_item = dill_utils_website_structure_get_data_for_selected_item(
				$this->wp->get_website_structure(),
				$this->wxtreectrl_manage_website_structure,
				$this->chosen_item_in_wxdialog_manage_website_structure
			);
			if( $selected_item === FALSE )
			{
				$this->show_error_dialog(
					ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
				);
				return FALSE;
			}

			// The new name must be unique in the node.
			$siblings = $this->wp->get_child_pages( $selected_item->get( "parent_id" ) );
			
			foreach( $siblings as $sibling )
			{
				if( strcmp($sibling->get( "name" ), $proposed_item_name ) == 0 )
				{
					// Error: The user has to select another name.
					$this->show_error_dialog(
						sprintf(
							ERROR_PAGENAME_EXISTS_IN_CURRENT_NODE,
							$proposed_item_name
						)
					);
					return FALSE;
				}
			}

			/* Try to rename the selected item.  On failure the body of the if
			branch is entered. */
			$this->wp->rename_page( $selected_item->get( "id" ), $proposed_item_name );
			
			/* The page name has been updated.  Refresh the related
			wxTreeCtrl widgets both in the main window and in the dialog to
			manage the website structure. */
			$this->wp->recreate_website_structure();
			$this->wxdialog_manage_website_structure_wxtreectrl_manage_website_structure_create_website_tree();
			$this->main_window_wxtreectrl_refresh_website_structure();
		}
	}


	function on_wxbutton_manage_website_structure_delete_item_clicked()
	{
		/* Handles the deletion of the selected item aswell as refreshing the
		related wxTreeCtrl widgets both in the main window and in the dialog to
		manage the structure of the website.

		On failure, FALSE is returned.

		First the 'id' (database id) of the selected item is fetched.
		Then this function calls another function to take care of the deletion.
		On sucess, the sort_id's are updated, so that all other elements remain
		in the same order and to ensure that added items in the future are
		appended to the end of a node.
		The relevant buttons to move an item, a branch or delete and rename an
		item are deactivated aswell (only on success).

		NOTE:  Children of an item are deleted aswell.  The database takes care
		of that.

		Parameters		None
		Return values	Void or FALSE
						FALSE is returned on failure.

		*/
		// Needed to get the 'id' (database value) of the selected element.
		$selected_item = dill_utils_website_structure_get_data_for_selected_item(
			$this->wp->get_website_structure(),
			$this->wxtreectrl_manage_website_structure,
			$this->chosen_item_in_wxdialog_manage_website_structure
		);
		if( $selected_item == FALSE )
		{
			$this->show_error_dialog(
				ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
			);
			return FALSE;
		}

		$this->wp->delete_page( $selected_item->get( "id" ) );
		
		/* The page which the user has selected (and any children) have been
		deleted.
		Redefine the 'sort_id' for every page in the node of where the
		selected item was located. */
		$remaining_siblings = $this->wp->get_child_pages( $selected_item->get( "parent_id" ) );

		$cnt1 = 0;
		foreach( $remaining_siblings as $key => $value )
		{
			$this->wp->page_update_sort_id( $value->get( "id" ), $cnt1 + 1 );
			$cnt1++;
		}
		
		/* Refresh the related wxTreeCtrl widgets that both represent the
		website structure. */
		$this->wp->recreate_website_structure();
		$this->wxdialog_manage_website_structure_wxtreectrl_manage_website_structure_create_website_tree();
		$this->main_window_wxtreectrl_refresh_website_structure();

		/* Set the label of the static text widget, which displays
		information about which templates a selected page uses, to "-". */
		$this->wxstatictext_main_window_website_structure_template_used->SetLabel(
			"-"
		);

		/* Deactivate all buttons except the "Add" button in the dialog to
		manage the website structure. */
		$this->wxbutton_manage_website_structure_rename_item->Disable();
		$this->wxbutton_manage_website_structure_delete_item->Disable();
		$this->wxbutton_manage_website_structure_move_up_item->Disable();
		$this->wxbutton_manage_website_structure_move_down_item->Disable();
		$this->wxbutton_manage_website_structure_relocate_itemtree->Disable();
		$this->wxbutton_manage_website_structure_change_template->Disable();
	}


	function on_wxbutton_manage_website_structure_move_up_item_clicked()
	{
		/* Handles moving a selected item up in the current node aswell as
		refresh the related wxTreeCtrl widgets.

		First the database data of the selected item is stored (array).
		Next the database data of the siblings of the selected item are stored
		(array of arrays).
		Next the 'id' of the item to move down in the node is stored.
		Afterwards the two items's order is reversed.
		Lastly, on success, the wxTreeCtrl widgets are updated to display the
		change.
		
		Parameters		None
		Return values	Void or FALSE
						FALSE is returned on failure.

		*/
		// Required to get the 'id' of the selected item.
		$selected_item = dill_utils_website_structure_get_data_for_selected_item(
			$this->wp->get_website_structure(),
			$this->wxtreectrl_manage_website_structure,
			$this->chosen_item_in_wxdialog_manage_website_structure
		);
		if( $selected_item === FALSE )
		{
			$this->show_error_dialog(
				ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
			);
			return FALSE;
		}

		// Required to get the 'id' of the sibling above the selected item.
		$siblings = $this->wp->get_child_pages( $selected_item->get( "parent_id" ) );

		// Get the 'id' and "sort_id" of the sibling to move down. 
		$item_to_move_up_id = $selected_item->get( "id" );
		$item_to_move_up_sort_id = $selected_item->get( "sort_id" ) - 1;

		$item_to_move_down_id = NULL;
		$item_to_move_down_sort_id = NULL;
		
		foreach( $siblings as $sibling )
		{
			if( $sibling->get( "sort_id" ) == ( $item_to_move_up_sort_id ) )
			{
				$item_to_move_down_id = $sibling->get( "id" );
				$item_to_move_down_sort_id = $sibling->get( "sort_id" ) + 1;
				break;
			}
		}

		/* Reverse those two items by changing their sort_ids's.
		On failure display an error dialog and return from the function. */
		$this->wp->reverse_two_page_items(
			$item_to_move_up_id,
			$item_to_move_up_sort_id,
			$item_to_move_down_id,
			$item_to_move_down_sort_id
		);

		// Refresh the related wxTreeCtrl widgets to make the change visible.
		$this->wp->recreate_website_structure();
		$this->wxdialog_manage_website_structure_wxtreectrl_manage_website_structure_create_website_tree();		
		$this->main_window_wxtreectrl_refresh_website_structure();		
	}


	function on_wxbutton_manage_website_structure_move_down_item_clicked()
	{
		/* Handles moving a selected item down in the current node.

		First we need to get database data for the selected item so we can get
		the id of it to assign it a new sort_id later on.
		Next we need to get database data for siblings of the selected item,
		which is an array of arrays.
		Then we need to store the id of the item that we want to move up.
		Then the items with the corresponding ids are moved.
		On sucess, the related wxTreeCtrl widgets are updated.  Otherwise an
		error dialog is shown and FALSE is returned.

		Parameters		None
		Return values	Void or FALSE
						FALSE is returned on failure.

		*/

		// Required to get the 'id' (database value) of the selected item.
		$selected_item = dill_utils_website_structure_get_data_for_selected_item(
			$this->wp->get_website_structure(),
			$this->wxtreectrl_manage_website_structure,
			$this->chosen_item_in_wxdialog_manage_website_structure
		);
		if( $selected_item === FALSE )
		{
			$this->show_error_dialog(
				ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
			);
			return FALSE;
		}

		/* Required to get the 'id' (database value) of the item that is below
		the current item. */
		$siblings = $this->wp->get_child_pages( $selected_item->get( "parent_id" ) );

		// Detect the 'id' of the item that needs to be moved up.
		$item_to_move_down_id = $selected_item->get( "id" );
		$item_to_move_down_sort_id = $selected_item->get( "sort_id" ) + 1;
		
		$item_to_move_up_id = NULL;
		$item_to_move_up_sort_id = NULL;
		
		foreach( $siblings as $sibling )
		{
			if( $sibling->get( "sort_id" ) == $item_to_move_down_sort_id )
			{
				$item_to_move_up_id = $sibling->get( "id" );
				$item_to_move_up_sort_id = $sibling->get( "sort_id" ) - 1;
				break;
			}
		}
		
		/* Flip the sort_id values (database values) of those two items of which
		the 'id' values have been found.
		On failure, enter the body of the if-statement, show the error dialog
		and return FALSE. */
		$this->wp->reverse_two_page_items(
			$item_to_move_up_id,
			$item_to_move_up_sort_id,
			$item_to_move_down_id,
			$item_to_move_down_sort_id
		);

		// Refresh the related wxTreeCtrl widgets to make the change visible.
		$this->wp->recreate_website_structure();
		$this->wxdialog_manage_website_structure_wxtreectrl_manage_website_structure_create_website_tree();
		$this->main_window_wxtreectrl_refresh_website_structure();
	}


	function on_wxbutton_manage_website_structure_relocate_itemtree_clicked()
	{
		/* Handles the entire process of moving the selected item(tree) into
		another item tree, or define it as a root item.

		First a dialog is created, through which an item tree can be moved.  This
		dialog consists of a wxTreeCtrl, that displays the website structure
		without the item(tree) that has been selected in the dialog to manage
		the website structure.
		It also has an "Ok" and a "Cancel" button.

		A click on "Ok" moves the selected item tree into another item (or
		defines it as a root item) by getting hold of the 'parent_id' and 'id'
		database values for the previously selected item and the selected item
		in the dialog itself, and setting the 'parent_id' of one item to be the
		'id' of the other item.

		On success, the related wxTreeCtrl items both in the main window and in
		the dialog for managing the website structure are refreshed.

		On any failure, FALSE is returned.

		Parameters		None
		Return values 	Void or FALSE
						FALSE is returned on failure.

		*/
		/* The 'parent_id' value (database id) of the selected item in the
		current wxTreeCtrl is required, so that the previously selected item(tree)
		may be moved into it.
		A parent item has the value 'NULL' for its 'parent_id'.*/
		$selected_item = dill_utils_website_structure_get_data_for_selected_item(
			$this->wp->get_website_structure(),
			$this->wxtreectrl_manage_website_structure,
			$this->chosen_item_in_wxdialog_manage_website_structure
		);
		if( $selected_item === FALSE )
		{
			$this->show_error_dialog(
				ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
			);
			return FALSE;
		}
		
		$parent_id = $selected_item->get( "parent_id" );

		/* Now we need to load the website structure without the current
		item branch of the currently selected item. */
		$website_structure_to_move_a_tree = db_get_website_structure(
			$this->db,
			NULL,
			array( $selected_item->get( "id" ) )
		);
		if( $website_structure_to_move_a_tree === FALSE )
		{
			$this->show_error_dialog(
				ERROR_DB_RETRIEVE_WEBSITE_STRUCTURE
			);
			return FALSE;
		}
		

		/* Create the dialog so the user can choose where to move a selected
		item(tree) into. */
		$wxdialog = new wxDialog(
			$this->wxdialog_manage_website_structure,
			wxID_ANY,
			TEXT_WXDIALOG_MANAGE_WEBSITE_STRUCTURE_RELOCATE_ITEMTREE
		);

		// Controls are placed into a panel.
		$wxpanel = new wxPanel(
			$wxdialog,
			wxID_ANY
		);

		/* Our dialog consists of a wxStaticText widget, a wxTreeCtrl widget
		and two wxButton widget instances.  All widgets are aligned vertically
		below each other, except for the two buttons, which are aligned hori-
		zontally. */
		
		// Create our wxBoxSizer widgets for aligning the other widgets.
		$wxvbox_all = new wxBoxSizer( wxVERTICAL );
		$wxvbox_top = new wxBoxSizer( wxVERTICAL );
		$wxhbox = new wxBoxSizer( wxHORIZONTAL );

		// Create the widgets which we're going to need.
		$wxstatictext = new wxStaticText(
			$wxpanel,
			wxID_ANY,
			TEXT_WXSTATICTEXT_MANAGE_WEBSITE_STRUCTURE_RELOCATE_ITEMTREE
		);

		$wxtreectrl = new mywxTreeCtrl(
			$wxpanel,
			wxID_ANY,
			wxDefaultPosition,
			wxDefaultSize,
			wxTR_SINGLE | wxTR_HIDE_ROOT | wxTR_HAS_BUTTONS
		);

		$wxbutton_ok = new wxButton(
			$wxpanel,
			wxID_OK,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_RELOCATE_ITEMTREE_OKAY
		);

		$wxbutton_cancel = new wxButton(
			$wxpanel,
			wxID_CANCEL,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_RELOCATE_ITEMTREE_CANCEL
		);

		// Add these widgets to the boxes.
		$wxvbox_top->Add(
			$wxstatictext,
			0,
			wxEXPAND
		);

		$wxvbox_top->Add(
			$wxtreectrl,
			1,
			wxEXPAND
		);

		$wxhbox->Add(
			$wxbutton_ok,
			1,
			wxEXPAND
		);

		$wxhbox->Add(
			$wxbutton_cancel,
			1,
			wxEXPAND
		);

		$wxvbox_all->Add(
			$wxvbox_top,
			1,
			wxEXPAND
		);

		$wxvbox_all->Add(
			$wxhbox,
			0,
			wxEXPAND
		);

		/* Make sure that all added widgets are shown when the dialog is
		displayed */
		$wxpanel->SetSizer( $wxvbox_all );
		$wxvbox_all->SetSizeHints( $wxdialog );

		/* Populate our wxTreeCtrl widget with the website structure for moving
		a selected item/branch.
		The previously selected item (and its children) will not be shown. */
		
		// The root node always is required.  It won't be shown.
		$rootid = $wxtreectrl->AddRoot( "Root" );
		
		/* Create the website structure that will be shown in the wxTreeCtrl of
		the dialog without the previously selected branch. */
		$this->create_website_structure_tree(
			$wxtreectrl,
			$this->wp->get_website_structure(),
			$rootid,
			array( $selected_item->get( "id" ) )
		);


		// Make sure that all website structure pages are shown immediately.
		$wxtreectrl->ExpandAll();

		/* Anonymous functions that are triggered as soon as the user either
		disselects or selects an item in the wxTreeCtrl widget. */
		$wxtreectrl->on_wxtreectrl_relocate_itemtree_right_click = function( $event, $test2 )
		{
			$test2->UnselectItem( $event->GetItem() );
			$test2->Unselect();
		};
		$wxtreectrl->on_wxtreectrl_relocate_itemtree_click = function( $event, $test2 )
		{
			$test2->SelectItem( $event->GetItem(), TRUE );
		};
		$wxtreectrl->Connect(
			wxEVT_TREE_ITEM_RIGHT_CLICK,
			array(
				$wxtreectrl,
				"on_wxtreectrl_relocate_itemtree_right_click"
			)
		);

		/* Show the dialog and enter the if-statement body if the user has
		clicked the "Ok" button. */
		if( $wxdialog->ShowModal() == wxID_OK )
		{
			/*  To move the selected itemtree, we need the 'id' of the item,
			which has been selected in this dialog.*/
			if( $wxtreectrl->GetSelection()->IsOk() == FALSE )
			{
				/* No item was selected, which means that the previously
				selected item is going to be a parent item. */
				$selected_item_in_wxtreectrl_relocate_itemtree_id = NULL;
			}
			else
			{
				$selected_item_in_wxtreectrl_relocate_itemtree = dill_utils_website_structure_get_data_for_selected_item(
					$this->wp->get_website_structure(),
					$wxtreectrl,
					$wxtreectrl->GetItemText( $wxtreectrl->GetSelection() )
				);
				if( $selected_item_in_wxtreectrl_relocate_itemtree === FALSE )
				{
					$this->show_error_dialog(
						ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
					);
					return FALSE;
				}
				$selected_item_in_wxtreectrl_relocate_itemtree_id = $selected_item_in_wxtreectrl_relocate_itemtree->get( "id" );
			}

			/* Try to change the parent_id of the previously selected item that
			we want to move.
			We also need to know, how many items there are in the branch, where
			we want to move our item, so we can assign new 'sort_id's. */
			$this->wp->move_page_into_page(
				count( $this->wp->get_child_pages( $selected_item_in_wxtreectrl_relocate_itemtree_id ) ) + 1,
				$selected_item->get( "id" ),
				$selected_item_in_wxtreectrl_relocate_itemtree_id			
			);

			/* The item/page has been moved.
			Reset all sort_id values of the branch, where the selected item
			used to be. */
			$this->wp->recreate_website_structure();			
			$old_siblings = $this->wp->get_child_pages( $selected_item->get( "parent_id" ) );

			$cnt1 = 0;
			foreach( $old_siblings as $item )
			{
				$this->wp->page_update_sort_id( $item->get( "id" ), $cnt1 + 1 );
				$cnt1++;
			}

			/* Refresh the related wxTreeCtrl widgets both in the main
			window and in the dialog for managing the website structure. */
			$this->wp->recreate_website_structure();
			$this->wxdialog_manage_website_structure_wxtreectrl_manage_website_structure_create_website_tree();
			$this->main_window_wxtreectrl_refresh_website_structure();
		}
	}


	function on_wxbutton_manage_website_structure_change_template_clicked()
	{
		/* This function shows a dialog through which the user can change the
		template of the selected item in the wxTreeCtrl widget.  It also handles
		changing the template and, on success, refresh the related wxTreeCtrl
		widgets.

		First database data for the selected item is stored in a variable as an
		array.  From this we need to know which item is currently being used.
		Next a list of all available templates is retrieved and stored as an
		array in another variable.
		Afterwards the dialog is created, from which the user can select a
		template to use.  On a click on "Ok", the function tries to change the
		templte.  On a click on "Cancel", nothing happens.
		On success, the related wxListBox widget is updated.

		Parameters		None
		Return values	Void or FALSE
						FALSE is returned upon failure.
		*/
		// Get the name of the template assigned to the selected item.
		$selected_item = dill_utils_website_structure_get_data_for_selected_item(
			$this->wp->get_website_structure(),
			$this->wxtreectrl_manage_website_structure,
			$this->chosen_item_in_wxdialog_manage_website_structure
		);
		if( $selected_item === FALSE )
		{
			$this->show_error_dialog(
				ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
			);
			return FALSE;
		}
		$selected_item_template = $selected_item->get( "template" );
			
		// Get a list of available templates to display them in the wxdialog widget.
		$list_of_available_templates = array_keys( $this->wp->get_elements( WEBSITE_PROJECT_TEMPLATE_FILES ) );

		/* The user can choose one new template in the dialog that is shown to
		him. */
		$wxdialog = new wxSingleChoiceDialog(
			$this->wxdialog_manage_website_structure,
			TEXT_WXDIALOG_MANAGE_WEBSITE_STRUCTURE_CHANGE_TEMPLATE,
			CAPTION_WXDIALOG_MANAGE_WEBSITE_STRUCTURE_CHANGE_TEMPLATE,
			$list_of_available_templates
		);

		// Display the dialog and enter the if-statement's body on a click on "Ok".
		if( $wxdialog->ShowModal() == wxID_OK )
		{
			// Store the name of the template that has been chosen.
			$chosen_template_name = $wxdialog->GetStringSelection();

			/* Change the template for the currently selected item if the
			selected template differs.  Otherwise do nothing. */
			if( strcmp( $chosen_template_name, $selected_item_template ) != 0 )
			{
				/* Now change the template.  Create new containers for the
				selected page if containers with the same name do not yet exist.
				Delete all old containers that do not exist within the new
				template anymore. */
				$this->wp->page_update_template( $selected_item->get( "id" ), $chosen_template_name, $selected_item_template );
				
				// Show the updated containers in the wxListBox of the main window.
				//$this->main_window_wxlistbox_containers_refresh_list();
				$this->wp->recreate_website_structure();
				$this->wxdialog_manage_website_structure_wxtreectrl_manage_website_structure_create_website_tree();
				$this->on_main_window_wxtreectrl_website_structure_sel_changed();
			}
		}
	}


	function refresh_main_window()
	{
		/* Calls functions to refresh the wxTreeCtrl widget aswell as the
		wxListBox widgets of the main window.

		Parameters		None
		Return values	Void or FALSE
						FALSE is returned on failure.

		*/
		$this->main_window_wxtreectrl_refresh_website_structure();
		$this->main_window_wxlistbox_css_refresh_list();
		$this->main_window_wxlistbox_javascript_refresh_list();
		$this->main_window_wxlistbox_modules_refresh_list();
		$this->main_window_wxlistbox_templates_refresh_list();
	}


	function main_window_wxtreectrl_refresh_website_structure()
	{
		/* Refreshes the wxTreeCtrl widget of the main window to display the
		actual website structure of the opened project.

		Parameters		None
		Return values	TRUE or FALSE
						FALSE is returned on failure.

		*/
		// Remove the existing tree first.
		$this->wxtreectrl_main_window_website_structure->DeleteAllItems();
		
		// Create a root node to assign a generated website structure to.
		$root_node = $this->wxtreectrl_main_window_website_structure->AddRoot(
			"Root"
		);

		$this->create_website_structure_tree(
			$this->wxtreectrl_main_window_website_structure,
			$this->wp->get_website_structure(),
			$root_node
		);		

		// Show all items of the tree to the user instantly.
		$this->wxtreectrl_main_window_website_structure->ExpandAll();

		return TRUE;
	}


	function main_window_wxlistbox_containers_refresh_list()
	{
		/* Refreshes the wxListBox widget to display the containers of a
		selected page in the wxTreeCtrl widget.
		Also empties the editor of the main window.

		Only refreshes the wxListBox widget that diplays the containers if a
		page has been chosen.
		
		Parameters		None
		Return values	Void or FALSE
						FALSE is returned on failure.

		*/

		$this->on_main_window_wxtreectrl_website_structure_sel_changed();
		
		// Clear the contents that are currently loaded in the editor.
		$this->wxtextctrl_main_window_editor->ClearAll();

		// Deselect any selections in other wxListBox widgets of the main window.
		if( ( $index = $this->wxlistbox_main_window_css->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_css->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_javascript->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_javascript->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_modules->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_modules->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_templates->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_templates->Deselect( $index );
		}


		/* Get data for the currently selected item in the wxTreeCtrl widget of
		the main window. */
		$selected_item = $this->wxtreectrl_main_window_website_structure->GetSelection();
		if( $selected_item->IsOk() )
		{
			$selected_item_name = $this->wxtreectrl_main_window_website_structure->GetItemText(
				$selected_item
			);
			$selected_item = dill_utils_website_structure_get_data_for_selected_item(	
				$this->wp->get_website_structure(),
				$this->wxtreectrl_main_window_website_structure,
				$selected_item_name
			);
			if( $selected_item === FALSE )
			{
				$this->show_error_dialog(
					ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
				);
				return FALSE;
			}

			// Store all the container names for the selected page in an array.
			$container_names = array();
			foreach( $selected_item->get( "containers" ) as $container_item )
			{
				$container_names[] = $container_item->get( "name" );
			}

			// Add the container names to the wxListBox widget.
			$this->wxlistbox_main_window_containers->Set( $container_names );
		}
	}


	function main_window_wxlistbox_css_refresh_list()
	{
		/* Updates the wxListBox of the main window that lists the CSS files.

		Parameters		Void
		Return values 	Void

		*/
		$this->wxlistbox_main_window_css->Set(
			array_keys(
				$this->wp->get_elements(
					WEBSITE_PROJECT_CSS_FILES 
				)
			)
		);
	}


	function main_window_wxlistbox_javascript_refresh_list()
	{
		/* Updates the wxListBox of the main window that lists the JS files.

		Parameters		Void
		Return values 	Void

		*/
		$this->wxlistbox_main_window_javascript->Set(
			array_keys(
				$this->wp->get_elements(
					WEBSITE_PROJECT_JAVASCRIPT_FILES
				)
			)
		);
	}


	function main_window_wxlistbox_modules_refresh_list()
	{
		/* Updates the wxListBox of the main window that lists modules.

		Parameters		Void
		Return values 	Void

		*/
		$this->wxlistbox_main_window_modules->Set(
			array_keys(
				$this->wp->get_elements(
					WEBSITE_PROJECT_MODULE_FILES
				)
			)
		);
	}


	function main_window_wxlistbox_templates_refresh_list()
	{
		/* Updates the wxListBox of the main window that lists templates, and
		additionally enables or disables the menu item to manage the website
		structure, depending on whether any templates exists.

		Parameters		Void
		Return values 	Void

		*/
		$this->wxlistbox_main_window_templates->Set(
			array_keys(
				$this->wp->get_elements(
					WEBSITE_PROJECT_TEMPLATE_FILES
				)
			)
		);		
	}			


	function on_website_project_opened()
	{
		/* This function does loads a website project by calling functions and
		setting necessary properties.

		Parameters		Void
		Return values	Void

		*/


		// Disable the menu items to create or open a website project. 
		$this->menu_main_window_file->Enable(
			WXID_MENU_MAIN_WINDOW_FILE_NEW_PROJECT,
			FALSE
		);
		$this->menu_main_window_file->Enable(
			WXID_MENU_MAIN_WINDOW_FILE_OPEN_PROJECT,
			FALSE
		);
		// Enable the menu to manage a website project.
		$this->menubar_main_window->EnableTop( 1, TRUE );

		// Load predefined data into the main window.
		 $this->refresh_main_window();		

		// Update the array of existing projects.
		$this->refresh_list_of_website_projects();
		

		/* The website structure can only be edited if at least one template
		exists. */
		if( count( $this->wp->get_elements( WEBSITE_PROJECT_TEMPLATE_FILES ) ) == 0 )
		{
			// Disable the menu item to alter the website structure.
			$this->menu_main_window_project->Enable(
				WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_WEBSITE_STRUCTURE,
				FALSE
			);		
		}

		/* Last but not least set global variables to point to certain paths.
		These global variables can be used by the user when modifing a module. */
		global $ABSPATH_CWP;
		$ABSPATH_CWP = makepath(
			ABSPATH_WEBSITE_PROJECTS,
			$this->website_project
		);
		
		global $ABSPATH_CWP_IN;		
		$ABSPATH_CWP_IN = makepath(
			$ABSPATH_CWP
		);
		
		global $ABSPATH_CWP_OUT;
		$ABSPATH_CWP_OUT = makepath(
			$ABSPATH_CWP
		);
		
		global $ABSPATH_CWP_OUT_CSS;
		$ABSPATH_CWP_OUT_CSS = makepath(
			$ABSPATH_CWP,
			RELPATH_WEBSITE_CSS
		);
		
		global $ABSPATH_CWP_OUT_JS;
		$ABSPATH_CWP_OUT_JS = makepath(
			$ABSPATH_CWP,
			RELPATH_WEBSITE_JS
		);
		
		global $ABSPATH_CWP_OUT_MEDIA;
		$ABSPATH_CWP_OUT_MEDIA = makepath(
			$ABSPATH_CWP,
			RELPATH_WEBSITE_MEDIA
		);
		
		global $ABSPATH_CWP_OUT_DOWNLOADS;
		$ABSPATH_CWP_OUT_DOWNLOADS = makepath(
			$ABSPATH_CWP,
			RELPATH_WEBSITE_DOWNLOADS
		);

		$dir_rep = dirwalk( $this->wp->abspath_media, array() );
		$this->populate_wxdataviewtreectrl( $this->wxdataviewtreectrl_main_window_media,
			$dir_rep
		);

		$dir_rep = dirwalk( $this->wp->abspath_downloads, array() );		
		$this->populate_wxdataviewtreectrl( $this->wxdataviewtreectrl_main_window_downloads,
			$dir_rep
		);	
		
	}


	function wxlistbox_manage_templates_refresh_list()
	{
		/* Refreshes the items that are shown in the wxListBox of the manage
		templates dialog.

		Parameters		Void
		Return values	Void

		*/
		$this->wxlistbox_manage_templates->Set(
			array_keys(
				$this->wp->get_elements(
					WEBSITE_PROJECT_TEMPLATE_FILES
				)
			)
		);	
	}


	function wxlistbox_manage_modules_refresh_list()
	{
		/* Refreshes the items that are shown in the wxListBox of the manage
		modules dialog.

		Parameters		Void
		Return values	Void

		*/
		$this->wxlistbox_manage_modules->Set(
			array_keys(
				$this->wp->get_elements(
					WEBSITE_PROJECT_MODULE_FILES
				)
			)
		);
	}


	function wxlistbox_manage_css_refresh_list()
	{
		/* Refreshes the items that are shown in the wxListBox of the manage
		css dialog.

		Parameters		Void
		Return values	Void

		*/	
		$this->wxlistbox_manage_css->Set(
			array_keys(
				$this->wp->get_elements(
					WEBSITE_PROJECT_CSS_FILES
				)
			)
		);
	}


	function wxlistbox_manage_js_refresh_list()
	{
		/* Refreshes the items that are shown in the wxListBox of the manage
		js dialog.

		Parameters		Void
		Return values	Void

		*/	
		$this->wxlistbox_manage_javascript->Set(
			array_keys(
				$this->wp->get_elements(
					WEBSITE_PROJECT_JAVASCRIPT_FILES
				)
			)
		);
	}


	function on_wxlistbox_main_window_templates_click()
	{
		/* Opens the selected template in the wxListBox of the main window, shows
		its content in the editor of the main window and disables other selections
		of the main window which would otherwise interfere.

		Parameters		Void
		Return values	Void or FALSE
						FALSE is returned on failure.

		For a detailed understanding of how this function works, please read
		through the body of this function.

		*/
		

		// Deselect any selections in other wxListBox widgets in the main window.
		if( ( $index = $this->wxlistbox_main_window_css->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_css->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_javascript->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_javascript->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_modules->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_modules->Deselect( $index );
		}

		/* Not sure why I am doing this.  Need to re-check later.  Probably to
		combat unexpected behaviour. */
		$sel_item = $this->wxtreectrl_main_window_website_structure->GetSelection();
		if( $sel_item->IsOk() )
		{
			$this->wxtreectrl_main_window_website_structure->Unselect();
		}

		/* Not sure why I am doing this.  Need to re-check later.  Probably to
		combat unexpected behaviour. */
		$this->wxlistbox_main_window_containers->Clear();
		$this->wxtextctrl_main_window_editor->ClearAll();		

		// Prepare the file whose contents are to be displayed in the editor:
		/* Get the name of the file that has been selected in the
		wxListBox widget. */
		$selection = $this->wxlistbox_main_window_templates->GetString(
			$this->wxlistbox_main_window_templates->GetSelection()
		);

		$content = $this->wp->get_elements( WEBSITE_PROJECT_TEMPLATE_FILES )[$selection]->get_content();
		$this->wxtextctrl_main_window_editor->SetText( $content );
		$this->wp->update_file_editing_info( WEBSITE_PROJECT_TEMPLATE_FILE, $selection );		
	}


	function on_wxbutton_main_window_save()
	{
		/* Controls what happens if the "Save" button of the main window is
		clicked.

		Parameters		Void
		Return values	Void or FALSE
						FALSE is returned on failure.

		For an understanding of how this function works, please continue reading
		the comments in the body of this function, aswell as the function calls
		themselves.

		*/

		// First of all, just save the content the file/database.
		$this->wp->save_editor_content( $this->wxtextctrl_main_window_editor->GetText() );
	}


	function on_wxlistbox_main_window_modules_click()
	{
		/* Unselects other selections of other wxListBox widgets in the main
		window, and displays the content of the selected module in the wxListBox
		widget of the main window.

		Parameters		Void
		Return values	Void or FALSE
						FALSE is returned on failure.

		For a detailed understanding of how this function works, please read the
		body of this function.

		*/
		// Deselect items of other wxListBox elements in the main window.
		if( ( $index = $this->wxlistbox_main_window_templates->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_templates->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_css->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_css->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_javascript->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_javascript->Deselect( $index );
		}

		/* Not sure why I do this.  Probably due to a bug ?  Will check later
		when refactoring. */
		$sel_item = $this->wxtreectrl_main_window_website_structure->GetSelection();
		if( $sel_item->IsOk() )
		{
			$this->wxtreectrl_main_window_website_structure->Unselect();
		}

		// Again, not sure why I do this.  Will check later during refactoring.
		$this->wxlistbox_main_window_containers->Clear();
		$this->wxtextctrl_main_window_editor->ClearAll();

		// Prepare the file whose contents are to be displayed in the editor:
		/* Get the name of the file that has been selected in the
		wxListBox widget. */
		$selection = $this->wxlistbox_main_window_modules->GetString(
			$this->wxlistbox_main_window_modules->GetSelection()
		);

		$content = $this->wp->get_elements( WEBSITE_PROJECT_MODULE_FILES )[$selection]->get_content();
		$this->wxtextctrl_main_window_editor->SetText( $content );
		$this->wp->update_file_editing_info( WEBSITE_PROJECT_MODULE_FILE, $selection );
	}


	function on_wxlistbox_main_window_css_click()
	{
		/* Unselects other selections of other wxListBox widgets in the main
		window, and displays the content of the selected css file, which has been
		selected in the wxListBox widget of the main window.

		Parameters		Void
		Return values	Void or FALSE

		For a detailed understanding of how this function works, please read the
		body of this function.

		*/
		// Deselect items of other wxListBox elements in the main window.		
		if( ( $index = $this->wxlistbox_main_window_templates->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_templates->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_javascript->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_javascript->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_modules->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_modules->Deselect( $index );
		}

		/* Not sure why I do this.  Probably due to a bug ?  Will check later
		when refactoring. */
		$sel_item = $this->wxtreectrl_main_window_website_structure->GetSelection();
		if( $sel_item->IsOk() )
		{
			$this->wxtreectrl_main_window_website_structure->Unselect();
		}

		// Again, not sure why I do this.  Will check later during refactoring.
		$this->wxlistbox_main_window_containers->Clear();
		$this->wxtextctrl_main_window_editor->ClearAll();
		

		// Prepare the file whose contents are to be displayed in the editor:
		/* Get the name of the file that has been selected in the
		wxListBox widget. */
		$selection = $this->wxlistbox_main_window_css->GetString(
			$this->wxlistbox_main_window_css->GetSelection()
		);

		$content = $this->wp->get_elements( WEBSITE_PROJECT_CSS_FILES )[$selection]->get_content();
		$this->wxtextctrl_main_window_editor->SetText( $content );
		$this->wp->update_file_editing_info( WEBSITE_PROJECT_CSS_FILE, $selection );	
	}


	function on_wxlistbox_main_window_js_click()
	{
		/* Unselects other selections of other wxListBox widgets in the main
		window, and displays the content of the selected css file, which has been
		selected in the wxListBox widget of the main window.

		Parameters		Void
		Return values	Void or FALSE
						FALSE is returned on failure.

		For a detailed understanding of how this function works, please read the
		body of this function.

		*/
		// Deselect items of other wxListBox elements in the main window.		
		if( ( $index = $this->wxlistbox_main_window_templates->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_templates->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_css->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_css->Deselect( $index );
		}
		if( ( $index = $this->wxlistbox_main_window_modules->GetSelection() ) != wxNOT_FOUND )
		{
			$this->wxlistbox_main_window_modules->Deselect( $index );
		}

		/* Not sure why I do this.  Probably due to a bug ?  Will check later
		when refactoring. */
		$sel_item = $this->wxtreectrl_main_window_website_structure->GetSelection();
		if( $sel_item->IsOk() )
		{
			$this->wxtreectrl_main_window_website_structure->Unselect();
		}

		// Again, not sure why I do this.  Will check later during refactoring.
		$this->wxlistbox_main_window_containers->Clear();
		$this->wxtextctrl_main_window_editor->ClearAll();


		// Prepare the file whose contents are to be displayed in the editor:
		/* Get the name of the javascript file that has been selected in the
		wxListBox widget. */
		$selection = $this->wxlistbox_main_window_javascript->GetString(
			$this->wxlistbox_main_window_javascript->GetSelection()
		);

		$content = $this->wp->get_elements( WEBSITE_PROJECT_JAVASCRIPT_FILES )[$selection]->get_content();
		$this->wxtextctrl_main_window_editor->SetText( $content );
		$this->wp->update_file_editing_info( WEBSITE_PROJECT_JAVASCRIPT_FILE, $selection );
	}


	function on_wxlistbox_main_window_containers_clicked()
	{
		/* Shows the content of the selected container in the editor.

		Parameters		Void
		Return values	Void or FALSE

		*/

		// Delete the contents of the editor in the main window.
		$this->wxtextctrl_main_window_editor->ClearAll();

		// Grab the relevant page.
		$selected_item_name = $this->wxtreectrl_main_window_website_structure->GetItemText(
			$this->wxtreectrl_main_window_website_structure->GetSelection()
		);
		$selected_page = dill_utils_website_structure_get_data_for_selected_item(	
			$this->wp->get_website_structure(),
			$this->wxtreectrl_main_window_website_structure,
			$selected_item_name
		);
		if( $selected_page === FALSE )
		{
			$this->show_error_dialog(
				ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
			);
			$this->current_website_project_editing_what = NULL;
			return FALSE;
		}

		$selected_container = NULL;
		// Store the name of the container that has been selected:
		$selected_container_name = $this->wxlistbox_main_window_containers->GetString(
			$this->wxlistbox_main_window_containers->GetSelection()
		);		
		foreach( $selected_page->get( "containers" ) as $container )
		{
			if( strcmp( $selected_container_name, $container->get( "name" ) ) == 0 )
			{
				// Now display the contents of the container that has been selected:
				$this->wxtextctrl_main_window_editor->SetValue(
					$container->get( "content" )
				);

				// Take note that a container is being edited:
				$this->wp->update_database_editing_info( $container->get( "id" ), $selected_page->get( "id" ) );	
				break;		
			}
		}
	}


	function on_main_window_wxtreectrl_website_structure_sel_changed()
	{
		/* Set the label of
		"$this->wxstatictext_main_window_website_structure_template_used" to the
		template that is used by the page that has just been selected.

		If no page has been selected, then nothing needs to be done. <-- Logic error.

		Parameters		Void
		Return values	Void or FALSE
						FALSE is returned on failure.

		*/

		$selected_item = $this->wxtreectrl_main_window_website_structure->GetSelection();
		if( $selected_item->IsOk() )
		{
			// Get database data for the page that has just been selected:
			$selected_item_name = $this->wxtreectrl_main_window_website_structure->GetItemText(
				$selected_item
			);
			$selected_item = dill_utils_website_structure_get_data_for_selected_item(	
				$this->wp->get_website_structure(),
				$this->wxtreectrl_main_window_website_structure,
				$selected_item_name
			);
			if( $selected_item === FALSE )
			{
				$this->show_error_dialog(
					ERROR_WEBSITE_STRUCTURE_GET_DATA_FOR_SELECTED_ITEM
				);
				$this->current_website_project_editing_what = NULL;
				return FALSE;
			}

			// Show the user which template the selected page uses.
			$this->wxstatictext_main_window_website_structure_template_used->SetLabel(
				$selected_item->get( "template" )
			);		
		}
	}


	function on_menu_main_window_project_manage_media()
	{
		/* Displays a wxDialog through which the user can manage media or
		download files, that is, add, rename and delete media files.

		Parameters		Void
		Return values	Void
		
		*/
		// Generate the tree:
		$this->wxdataviewtreectrl_manage_media->DeleteAllItems();
		$dir_rep = dirwalk( $this->wp->abspath_media, array() );
		$this->populate_wxdataviewtreectrl( $this->wxdataviewtreectrl_manage_media, $dir_rep );

		// Show the dialog.		
		$this->wxdialog_manage_media->ShowModal();
	}


	function on_manage_media_wxbutton_delete()
	{
		$abspath = makepath(
			$this->wp->abspath_media,
			$this->wxdataviewtreectrl_manage_media->GetItemData(
				$this->wxdataviewtreectrl_manage_media->GetSelection()
			)->relpath
		);

		/* Remove the directory (including subdirectories and files) or just
		a file. */
		if( is_file( $abspath ) )
		{
			unlink( $abspath );
		}
		else if( is_dir( $abspath ) )
		{
			rmtree( $abspath );
		}

		// Refresh the tree represented by wxdataviewtreectrl.
		$this->on_menu_main_window_project_manage_media_additional_dialogs_close();
	}


	function on_manage_media_wxbutton_add_directory()
	{
		/* Add a root directory if no item has been chosen.  Add a child
		directory if a directory has been chosen.

		*/
		// Test wheter an item is chosen.  Define a filepath in both cases.
		$wxdataviewitem = $this->wxdataviewtreectrl_manage_media->GetSelection();
		if( $wxdataviewitem->IsOk() )
		{
			$abspath_directory = makepath(
				$this->wp->abspath_media,
				$this->wxdataviewtreectrl_manage_media->GetItemData( $wxdataviewitem )->relpath
			);
		}
		else
		{
			$abspath_directory = $this->wp->abspath_media;
		}

		/* Create a wxTextEntryDialog, through which the user can type in the name
		of a new directory that will be added as soon as the user has clicked "Ok".
		*/
		$wxtextentrydialog = new wxTextEntryDialog(
			$this->wxdialog_manage_media,
			TEXT_WXDIALOG_MANAGE_MEDIA_DOWNLOADS_ADD_DIRECTORY,
			CAPTION_WXDIALOG_MANAGE_MEDIA_DOWNLOADS_ADD_DIRECTORY,
			""
		);

		// Show the dialog.
		if( $wxtextentrydialog->ShowModal() == wxID_OK )
		{
			// Try to add create the new directory.
			$proposed_directory_name = $wxtextentrydialog->GetValue();
			if( strlen( $proposed_directory_name ) > 0 )
			{
				// Create the directory.
				mkdir(
					makepath(
						$abspath_directory,
						$proposed_directory_name
					),
					0777,
					TRUE
				);

				// Refresh the wxDataViewTreeCtrl widget.
				$this->on_menu_main_window_project_manage_media_additional_dialogs_close();
			}
		}
	}


	function on_manage_media_wxdataviewtreectrl_selection_changed( $event )
	{
		if( $event->GetItem()->IsOk() )
		{		
		
			$abspath = makepath(
				$this->wp->abspath_media,
				$this->wxdataviewtreectrl_manage_media->GetItemData(
					$this->wxdataviewtreectrl_manage_media->GetSelection()
				)->relpath
			);

			/* The button to delete a file or a directory containing files and
			directory is always activated.  The same goes for the button to re-
			name a file or a directory. */
			$this->wxbutton_delete_manage_media->Enable( TRUE );
			$this->wxbutton_rename_manage_media->Enable( TRUE );
			
			if( is_file( $abspath ) )
			{
				// Deactivate the button to add a new item.
				$this->wxbutton_add_file_manage_media->Enable( FALSE );
				$this->wxbutton_add_directory_manage_media->Enable( FALSE );
			}
			else
			{
				// Activate the button to add a new item.
				$this->wxbutton_add_file_manage_media->Enable( TRUE );
				$this->wxbutton_add_directory_manage_media->Enable( TRUE );
			}
		}
	}


	function on_manage_media_wxdataviewtreectrl_right_click( $event )
	{
		/* Deselct the selection, if the user has clicked on a valid item and
		enable the button to add a new item. */

		$this->wxbutton_add_file_manage_media->Enable( TRUE );
		$this->wxbutton_add_directory_manage_media->Enable( TRUE );
		$this->wxbutton_delete_manage_media->Enable( FALSE );
		$this->wxbutton_rename_manage_media->Enable( FALSE );
		$this->wxdataviewtreectrl_manage_media->Unselect(
			$this->wxdataviewtreectrl_manage_media->GetSelection()
		);
	}


	function populate_wxdataviewtreectrl( $wxdataviewtreectrl, $data, $parent = NULL, $path = "" )
	{
		foreach( $data as $key => $value )
		{
			if( is_array( $value ) )
			{
				// Directories.
				if( $parent == NULL )
				{
					$wxclientdata = new wxClientData();
					if( $path != "" )
					{
						$wxclientdata->relpath = makepath( $path, $key );
					}
					else
					{
						$wxclientdata->relpath = makepath( $key );
					}
					$this->wp->managing_client_data[] = $wxclientdata;
					$parent_container = $wxdataviewtreectrl->AppendContainer(
						new wxDataViewItem(),
						$key,
						-1,
						TRUE
					);
					$wxdataviewtreectrl->Expand( $parent_container );
					$wxdataviewtreectrl->SetItemData( $parent_container, $wxclientdata );					
				}
				else
				{
					$wxclientdata = new wxClientData();
					if( $path != "" )
					{
						$wxclientdata->relpath = makepath( $path, $key );
					}
					else
					{
						$wxclientdata->relpath = makepath( $key );
					}
					$this->wp->managing_client_data[] = $wxclientdata;					
					$parent_container = $wxdataviewtreectrl->AppendContainer(
						$parent,
						$key,
						-1,
						TRUE
					);
					$wxdataviewtreectrl->Expand( $parent_container );
					$wxdataviewtreectrl->SetItemData( $parent_container, $wxclientdata );
				}
				$this->populate_wxdataviewtreectrl( $wxdataviewtreectrl, $value, $parent_container, $wxclientdata->relpath );
			}
			else
			{
				// Files.
				if( $parent == NULL )
				{
					$wxclientdata = new wxClientData();
					if( $path != "" )
					{
						$wxclientdata->relpath = makepath( $path, $value );
					}
					else
					{
						$wxclientdata->relpath = makepath( $value );
					}
					$this->wp->managing_client_data[] = $wxclientdata;					
					$res = $wxdataviewtreectrl->AppendItem(
						new wxDataViewItem(),
						$value,
						-1
					);
					$wxdataviewtreectrl->SetItemData( $res, $wxclientdata );
					$wxclientdata = NULL;
				}
				else
				{
					$wxclientdata = new wxClientData();
					if( $path != "" )
					{
						$wxclientdata->relpath = makepath( $path, $value );
					}
					else
					{
						$wxclientdata->relpath = makepath( $value );
					}
					$this->wp->managing_client_data[] = $wxclientdata;					
					$res = $wxdataviewtreectrl->AppendItem(
						$parent,
						$value,
						-1
					);
					$wxdataviewtreectrl->SetItemData( $res, $wxclientdata );
					$wxclientdata = NULL;					
				}
			}
		}
	}


	function on_menu_main_window_project_manage_media_add_file( $event )
	{
		$wxfiledialog = new wxFileDialog(
			$this->wxdialog_manage_media,
			TEXT_WXFILEDIALOG_MANAGE_MEDIA_DOWNLOADS_ADD_FILE
		);

		
		if( $wxfiledialog->ShowModal() == wxID_OK )
		{
			/* The user has clicked on the "open" button.  Copy the selected
			file (if any) to the directory that has been selected in the
			wxDataViewTreeCtrl widget. */
			$file_src_path = $wxfiledialog->GetPath();
			$file_dst_path_dir = $this->wp->abspath_media;
	
			$wxdataviewitem = $this->wxdataviewtreectrl_manage_media->GetSelection();
			if( !$wxdataviewitem->IsOk() )
			{
				$file_dst_path = makepath(
					$file_dst_path_dir,
					basename( $file_src_path )
				);
			}
			else
			{
				// Copy the selected file to a directory.
				$file_dst_path = makepath(
					$file_dst_path_dir,
					$this->wxdataviewtreectrl_manage_media->GetItemData( $wxdataviewitem )->relpath,
					basename( $file_src_path )
				);
			}

			// Copy.
			copy( $file_src_path, $file_dst_path );

			// Refresh the wxDataViewTreeCtrl widget.
			$this->on_menu_main_window_project_manage_media_additional_dialogs_close();
		}
	}


	function on_menu_main_window_project_manage_media_rename()
	{
		// Create a dialog through which the user can rename a file or directory.
		$wxtextentrydialog = new wxTextEntryDialog(
			$this->wxdialog_manage_media,
			TEXT_WXDIALOG_MANAGE_MEDIA_DOWNLOADS_RENAME,
			CAPTION_WXDIALOG_MANAGE_MEDIA_DOWNLOADS_RENAME,
			$this->wxdataviewtreectrl_manage_media->GetItemText(
				$this->wxdataviewtreectrl_manage_media->GetSelection()
			)
		);

		// Show the dialog.
		if( $wxtextentrydialog->ShowModal() == wxID_OK )
		{
			// Grab the absolute path to either the media or the downloads directory.
			$file_dst_path_dir = $this->wp->abspath_media;
			$new_filename = $wxtextentrydialog->GetValue();
			
			// A file within the same directory with the same name musn't exist.
			$wxclientdata = $this->wxdataviewtreectrl_manage_media->GetItemData(
				$this->wxdataviewtreectrl_manage_media->GetSelection()
			);
			$current_filename = $this->wxdataviewtreectrl_manage_media->GetItemText(
				$this->wxdataviewtreectrl_manage_media->GetSelection()
			);
			$current_abspath_file = makepath(
				$file_dst_path_dir,
				$wxclientdata->relpath
			);
			$current_abspath_dir = dirname( $current_abspath_file );

			if( !file_exists( makepath( $current_abspath_dir, $new_filename ) ) )
			{
				// Rename the existing file.
				$result = rename(
					$current_abspath_file,
					makepath( $current_abspath_dir, $new_filename )
				);

				// Refresh the wxDataViewTreeCtrl widget.
				$this->on_menu_main_window_project_manage_media_additional_dialogs_close();
			}
		}
	}


	function on_menu_main_window_project_manage_media_additional_dialogs_close()
	{
		/* Get a reference to the wxDataViewTreeCtrl widget of the manage media
		downloads dialog. */
		
		// Refresh the tree:
		$this->wxdataviewtreectrl_manage_media->DeleteAllItems();
		$dir_rep = dirwalk( $this->wp->abspath_media, array() );
		$this->populate_wxdataviewtreectrl( $this->wxdataviewtreectrl_manage_media, $dir_rep );

		$this->wxdataviewtreectrl_main_window_media->DeleteAllItems();
		$this->populate_wxdataviewtreectrl( $this->wxdataviewtreectrl_main_window_media, $dir_rep );

		if( count( $dir_rep ) == 0 )
		{
			// Enable the buttons to add a file or create a directory.
			// Disable the buttons to rename or delete a file/directory.
			$this->wxbutton_add_file_manage_media->Enable( TRUE );
			$this->wxbutton_add_directory_manage_media->Enable( TRUE );
			$this->wxbutton_delete_manage_media->Enable( FALSE );
			$this->wxbutton_rename_manage_media->Enable( FALSE );
		}
	}


	function on_menu_main_window_project_manage_downloads()
	{
		/* Displays a wxDialog through which the user can manage downloads or
		download files, that is, add, rename and delete downloads files.

		Parameters		Void
		Return values	Void
		
		*/
		// Generate the tree:
		$this->wxdataviewtreectrl_manage_downloads->DeleteAllItems();
		$dir_rep = dirwalk( $this->wp->abspath_downloads, array() );
		$this->populate_wxdataviewtreectrl( $this->wxdataviewtreectrl_manage_downloads, $dir_rep );

		// Show the dialog.		
		$this->wxdialog_manage_downloads->ShowModal();
	}


	function on_manage_downloads_wxbutton_delete()
	{
		$abspath = makepath(
			$this->wp->abspath_downloads,
			$this->wxdataviewtreectrl_manage_downloads->GetItemData(
				$this->wxdataviewtreectrl_manage_downloads->GetSelection()
			)->relpath
		);

		/* Remove the directory (including subdirectories and files) or just
		a file. */
		if( is_file( $abspath ) )
		{
			unlink( $abspath );
		}
		else if( is_dir( $abspath ) )
		{
			rmtree( $abspath );
		}

		// Refresh the tree represented by wxdataviewtreectrl.
		$this->on_menu_main_window_project_manage_downloads_additional_dialogs_close();
	}


	function on_manage_downloads_wxbutton_add_directory()
	{
		/* Add a root directory if no item has been chosen.  Add a child
		directory if a directory has been chosen.

		*/
		// Test wheter an item is chosen.  Define a filepath in both cases.
		$wxdataviewitem = $this->wxdataviewtreectrl_manage_downloads->GetSelection();
		if( $wxdataviewitem->IsOk() )
		{
			$abspath_directory = makepath(
				$this->wp->abspath_downloads,
				$this->wxdataviewtreectrl_manage_downloads->GetItemData( $wxdataviewitem )->relpath
			);
		}
		else
		{
			$abspath_directory = $this->wp->abspath_downloads;
		}

		/* Create a wxTextEntryDialog, through which the user can type in the name
		of a new directory that will be added as soon as the user has clicked "Ok".
		*/
		$wxtextentrydialog = new wxTextEntryDialog(
			$this->wxdialog_manage_downloads,
			TEXT_WXDIALOG_MANAGE_MEDIA_DOWNLOADS_ADD_DIRECTORY,
			CAPTION_WXDIALOG_MANAGE_MEDIA_DOWNLOADS_ADD_DIRECTORY,
			""
		);

		// Show the dialog.
		if( $wxtextentrydialog->ShowModal() == wxID_OK )
		{
			// Try to add create the new directory.
			$proposed_directory_name = $wxtextentrydialog->GetValue();
			if( strlen( $proposed_directory_name ) > 0 )
			{
				// Create the directory.
				mkdir(
					makepath(
						$abspath_directory,
						$proposed_directory_name
					),
					0777,
					TRUE
				);

				// Refresh the wxDataViewTreeCtrl widget.
				$this->on_menu_main_window_project_manage_downloads_additional_dialogs_close();
			}
		}
	}


	function on_manage_downloads_wxdataviewtreectrl_selection_changed( $event )
	{
		if( $event->GetItem()->IsOk() )
		{		
		
			$abspath = makepath(
				$this->wp->abspath_downloads,
				$this->wxdataviewtreectrl_manage_downloads->GetItemData(
					$this->wxdataviewtreectrl_manage_downloads->GetSelection()
				)->relpath
			);

			/* The button to delete a file or a directory containing files and
			directory is always activated.  The same goes for the button to re-
			name a file or a directory. */
			$this->wxbutton_delete_manage_downloads->Enable( TRUE );
			$this->wxbutton_rename_manage_downloads->Enable( TRUE );
			
			if( is_file( $abspath ) )
			{
				// Deactivate the button to add a new item.
				$this->wxbutton_add_file_manage_downloads->Enable( FALSE );
				$this->wxbutton_add_directory_manage_downloads->Enable( FALSE );
			}
			else
			{
				// Activate the button to add a new item.
				$this->wxbutton_add_file_manage_downloads->Enable( TRUE );
				$this->wxbutton_add_directory_manage_downloads->Enable( TRUE );
			}
		}
	}


	function on_manage_downloads_wxdataviewtreectrl_right_click( $event )
	{
		/* Deselct the selection, if the user has clicked on a valid item and
		enable the button to add a new item. */

		$this->wxbutton_add_file_manage_downloads->Enable( TRUE );
		$this->wxbutton_add_directory_manage_downloads->Enable( TRUE );
		$this->wxbutton_delete_manage_downloads->Enable( FALSE );
		$this->wxbutton_rename_manage_downloads->Enable( FALSE );
		$this->wxdataviewtreectrl_manage_downloads->Unselect(
			$this->wxdataviewtreectrl_manage_downloads->GetSelection()
		);
	}


	function on_menu_main_window_project_manage_downloads_add_file( $event )
	{
		$wxfiledialog = new wxFileDialog(
			$this->wxdialog_manage_downloads,
			TEXT_WXFILEDIALOG_MANAGE_MEDIA_DOWNLOADS_ADD_FILE
		);

		
		if( $wxfiledialog->ShowModal() == wxID_OK )
		{
			/* The user has clicked on the "open" button.  Copy the selected
			file (if any) to the directory that has been selected in the
			wxDataViewTreeCtrl widget. */
			$file_src_path = $wxfiledialog->GetPath();
			$file_dst_path_dir = $this->wp->abspath_downloads;
	
			$wxdataviewitem = $this->wxdataviewtreectrl_manage_downloads->GetSelection();
			if( !$wxdataviewitem->IsOk() )
			{
				$file_dst_path = makepath(
					$file_dst_path_dir,
					basename( $file_src_path )
				);
			}
			else
			{
				// Copy the selected file to a directory.
				$file_dst_path = makepath(
					$file_dst_path_dir,
					$this->wxdataviewtreectrl_manage_downloads->GetItemData( $wxdataviewitem )->relpath,
					basename( $file_src_path )
				);
			}

			// Copy.
			copy( $file_src_path, $file_dst_path );

			// Refresh the wxDataViewTreeCtrl widget.
			$this->on_menu_main_window_project_manage_downloads_additional_dialogs_close();
		}
	}


	function on_menu_main_window_project_manage_downloads_rename()
	{
		// Create a dialog through which the user can rename a file or directory.
		$wxtextentrydialog = new wxTextEntryDialog(
			$this->wxdialog_manage_downloads,
			TEXT_WXDIALOG_MANAGE_MEDIA_DOWNLOADS_RENAME,
			CAPTION_WXDIALOG_MANAGE_MEDIA_DOWNLOADS_RENAME,
			$this->wxdataviewtreectrl_manage_downloads->GetItemText(
				$this->wxdataviewtreectrl_manage_downloads->GetSelection()
			)
		);

		// Show the dialog.
		if( $wxtextentrydialog->ShowModal() == wxID_OK )
		{
			// Grab the absolute path to either the downloads or the downloads directory.
			$file_dst_path_dir = $this->wp->abspath_downloads;
			$new_filename = $wxtextentrydialog->GetValue();
			
			// A file within the same directory with the same name musn't exist.
			$wxclientdata = $this->wxdataviewtreectrl_manage_downloads->GetItemData(
				$this->wxdataviewtreectrl_manage_downloads->GetSelection()
			);
			$current_filename = $this->wxdataviewtreectrl_manage_downloads->GetItemText(
				$this->wxdataviewtreectrl_manage_downloads->GetSelection()
			);
			$current_abspath_file = makepath(
				$file_dst_path_dir,
				$wxclientdata->relpath
			);
			$current_abspath_dir = dirname( $current_abspath_file );

			if( !file_exists( makepath( $current_abspath_dir, $new_filename ) ) )
			{
				// Rename the existing file.
				$result = rename(
					$current_abspath_file,
					makepath( $current_abspath_dir, $new_filename )
				);

				// Refresh the wxDataViewTreeCtrl widget.
				$this->on_menu_main_window_project_manage_downloads_additional_dialogs_close();
			}
		}
	}


	function on_menu_main_window_project_manage_downloads_additional_dialogs_close()
	{
		/* Get a reference to the wxDataViewTreeCtrl widget of the manage downloads
		downloads dialog. */
		
		// Refresh the tree:
		$this->wxdataviewtreectrl_manage_downloads->DeleteAllItems();
		$dir_rep = dirwalk( $this->wp->abspath_downloads, array() );
		$this->populate_wxdataviewtreectrl( $this->wxdataviewtreectrl_manage_downloads, $dir_rep );

		$this->wxdataviewtreectrl_main_window_downloads->DeleteAllItems();
		$this->populate_wxdataviewtreectrl( $this->wxdataviewtreectrl_main_window_downloads, $dir_rep );

		if( count( $dir_rep ) == 0 )
		{
			// Enable the buttons to add a file or create a directory.
			// Disable the buttons to rename or delete a file/directory.
			$this->wxbutton_add_file_manage_downloads->Enable( TRUE );
			$this->wxbutton_add_directory_manage_downloads->Enable( TRUE );
			$this->wxbutton_delete_manage_downloads->Enable( FALSE );
			$this->wxbutton_rename_manage_downloads->Enable( FALSE );
		}
	}	
	
	


	function __construct()
	{
		parent::__construct(
			null,
			null,
			PROJECT_TITLE,
			wxDefaultPosition,
			new wxSize( 640, 480 )
		);

		$this->Maximize();

		// The panel for the main window.
		$this->panel_main_window = new wxPanel( $this, wxID_ANY );

		// The main menu bar.
		$this->menubar_main_window = new wxMenuBar();

		// And attach the main menu bar.
		$this->SetMenuBar( $this->menubar_main_window );

		// The file menu.
		$this->menu_main_window_file = new wxMenu();
		$this->menu_main_window_file->Append(
			WXID_MENU_MAIN_WINDOW_FILE_NEW_PROJECT,
			TEXT_NEW_PROJECT,
			TEXT_NEW_PROJECT_STATUSBAR
		);

		$this->menu_main_window_file->Append(
			WXID_MENU_MAIN_WINDOW_FILE_OPEN_PROJECT,
			TEXT_OPEN_PROJECT,
			TEXT_OPEN_PROJECT_STATUSBAR
		);

		$this->menu_main_window_file->Append(
			wxID_EXIT,
			TEXT_CLOSE_APPLICATION,
			TEXT_CLOSE_APPLICATION_STATUSBAR
		);

		// Add the file menu to the main menu.
		$this->menubar_main_window->Append(
			$this->menu_main_window_file,
			TEXT_MENUBAR_FILE
		);


		// The project menu.
		$this->menu_main_window_project = new wxMenu();

		$this->menu_main_window_project->Append(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_WEBSITE_STRUCTURE,
			TEXT_MENU_MAIN_WINDOW_PROJECT_MANAGE_WEBSITE_STRUCTURE,
			TEXT_STATUSBAR_MAIN_WINDOW_MANAGE_WEBSITE_STRUCTURE
		);
		
		$this->menu_main_window_project->Append(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_TEMPLATES,
			TEXT_MENU_MAIN_WINDOW_PROJECT_MANAGE_TEMPLATES,
			TEXT_MENU_MAIN_WINDOW_PROJECT_MANAGE_TEMPLATES_STATUSBAR
		);

		$this->menu_main_window_project->Append(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_MODULES,
			TEXT_MENU_MAIN_WINDOW_PROJECT_MANAGE_MODULES,
			TEXT_MENU_MAIN_WINDOW_PROJECT_MANAGE_MODULES_STATUSBAR
		);

		$this->menu_main_window_project->Append(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_JAVASCRIPT,
			TEXT_MENU_MAIN_WINDOW_PROJECT_MANAGE_JAVASCRIPT,
			TEXT_STATUSBAR_MAIN_WINDOW_MANAGE_PROJECT_JAVASCRIPT
		);

		$this->menu_main_window_project->Append(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_CSS,
			TEXT_MENU_MAIN_WINDOW_PROJECT_MANAGE_CSS,
			TEXT_STATUSBAR_MAIN_WINDOW_MANAGE_PROJECT_CSS
		);

		$this->menu_main_window_project->AppendSeparator();		

		// Media files can be added, renamed and removed.
		$this->menu_main_window_project->Append(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_MEDIA,
			TEXT_MENU_MAIN_WINDOW_PROJECT_MANAGE_MEDIA,
			TEXT_STATUSBAR_MAIN_WINDOW_MANAGE_MEDIA
		);
		
		// Download files can be added, renamed and removed.		
		$this->menu_main_window_project->Append(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_DOWNLOADS,
			TEXT_MENU_MAIN_WINDOW_PROJECT_MANAGE_DOWNLOADS,
			TEXT_STATUSBAR_MAIN_WINDOW_MANAGE_DOWNLOADS
		);		

		$this->menu_main_window_project->AppendSeparator();

		$this->menu_main_window_project->Append(
			WXID_MENU_MAIN_WINDOW_PROJECT_GENERATEWEBSITE,
			TEXT_MENU_MAIN_WINDOW_PROJECT_GENERATEWEBSITE,
			TEXT_STATUSBAR_MAIN_WINDOW_GENERATEWEBSITE
		);

		$this->menu_main_window_project->AppendSeparator();		

		$this->menu_main_window_project->Append(
			WXID_MENU_MAIN_WINDOW_PROJECT_CLOSE,
			TEXT_MENU_MAIN_WINDOW_PROJECT_CLOSE,
			TEXT_STATUSBAR_MAIN_WINDOW_PROJECT_CLOSE
		);

		// Add the project menu to the main menu.
		$this->menubar_main_window->Append(
			$this->menu_main_window_project,
			TEXT_MAIN_MENUBAR_PROJECT
		);	


		// The help menu.
		$this->menu_main_window_help = new wxMenu();
		$this->menu_main_window_help->Append(
			WXID_MENU_MAIN_WINDOW_HELP_HELP,
			TEXT_MENU_MAIN_WINDOW_HELP_HELP,
			TEXT_STATUSBAR_MAIN_WINDOW_HELP_HELP
		);
		$this->menu_main_window_help->Append(
			WXID_MENU_MAIN_WINDOW_HELP_ABOUT,
			TEXT_MENU_MAIN_WINDOW_HELP_ABOUT,
			TEXT_STATUSBAR_MAIN_WINDOW_HELP_ABOUT
		);

		// Add the help menu to the main menu.
		$this->menubar_main_window->Append(
			$this->menu_main_window_help,
			TEXT_MAIN_MENUBAR_HELP
		);

		// The project menu is deactivated at the beginning.
		$this->menubar_main_window->EnableTop( 1, FALSE );			


		// The status menu bar.
		$this->statusbar_main_window = $this->CreateStatusBar( TRUE );


		// Controls inside the mainframe.
		// All controls are contained in a horizontal box.
		$this->hbox_main_window_controls = new wxBoxSizer( wxHORIZONTAL );

		/* The editor is in the center.  The remaining elements are on the left
		and right. */


		$this->vbox_main_window_other_controls = new wxBoxSizer( wxVERTICAL );
		// The website structure is displayed as a tree structure.
		$this->wxstatictext_main_window_website_structure = new wxStaticText(
			$this->panel_main_window,
			WXID_MAIN_WINDOW_WEBSITE_STRUCTURE_STATICTEXT,
			TEXT_MAIN_WINDOW_WEBSITE_STRUCTURE_STATICTEXT
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxstatictext_main_window_website_structure,
			0,
			wxEXPAND
		);
		$this->wxtreectrl_main_window_website_structure = new wxTreeCtrl(
			$this->panel_main_window,
			WXID_MAIN_WINDOW_WEBSITE_STRUCTURE,
			wxDefaultPosition,
			wxDefaultSize,
			wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxtreectrl_main_window_website_structure,
			1,
			wxEXPAND
		);

		/* Two static texts for displaying information about which page uses
		which template. */
		$this->wxstatictext_main_window_website_structure_template_used_heading = new wxStaticText(
			$this->panel_main_window,
			WXID_MAIN_WINDOW_WEBSITE_STRUCTURE_TEMPLATE_USED_HEADING,
			TEXT_MAIN_WINDOW_WEBSITE_STRUCTURE_TEMPLATE_USED_HEADING
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxstatictext_main_window_website_structure_template_used_heading,
			0,
			wxEXPAND
		);
		$this->wxstatictext_main_window_website_structure_template_used = new wxStaticText(
			$this->panel_main_window,
			WXID_MAIN_WINDOW_WEBSITE_STRUCTURE_TEMPLATE_USED,
			TEXT_MAIN_WINDOW_WEBSITE_STRUCTURE_TEMPLATE_USED_DEFAULT
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxstatictext_main_window_website_structure_template_used,
			0,
			wxEXPAND
		);

		/* Containers of an element are shown as soon as an element of the
		website structure has been chosen.
		They are displayed as elements in a simple wxListBox. */
		$this->wxstatictext_main_window_containers = new wxStaticText(
			$this->panel_main_window,
			WXID_STATICTEXT_MAIN_WINDOW_CONTAINERS,
			TEXT_STATICTEXT_MAIN_WINDOW_CONTAINERS
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxstatictext_main_window_containers,
			0
		);
		$this->wxlistbox_main_window_containers = new wxListBox(
			$this->panel_main_window,
			WXID_WXLISTBOX_MAIN_WINDOW_CONTAINERS,
			wxDefaultPosition,
			wxDefaultSize,
			array(),
			wxLB_SINGLE | wxLB_ALWAYS_SB | wxLB_SORT
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxlistbox_main_window_containers,
			1,
			wxEXPAND
		);

		// A static text + a listbox for the templates of a website project.
		$this->wxstatictext_main_window_templates = new wxStaticText(
			$this->panel_main_window,
			WXID_STATICTEXT_MAIN_WINDOW_TEMPLATES,
			TEXT_STATICTEXT_MAIN_WINDOW_TEMPLATES
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxstatictext_main_window_templates,
			0
		);
		$this->wxlistbox_main_window_templates = new wxListBox(
			$this->panel_main_window,
			WXID_WXLISTBOX_MAIN_WINDOW_TEMPLATES,
			wxDefaultPosition,
			wxDefaultSize,
			array(),
			wxLB_SINGLE | wxLB_ALWAYS_SB | wxLB_SORT
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxlistbox_main_window_templates,
			1,
			wxEXPAND
		);

		// A static text + a listbox for the modules of a website project.
		$this->wxstatictext_main_window_modules = new wxStaticText(
			$this->panel_main_window,
			WXID_WXSTATICTEXT_MAIN_WINDOW_MODULES,
			TEXT_WXSTATICTEXT_MAIN_WINDOW_MODULES
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxstatictext_main_window_modules,
			0
		);
		$this->wxlistbox_main_window_modules = new wxListBox(
			$this->panel_main_window,
			WXID_WXLISTBOX_MAIN_WINDOW_MODULES,
			wxDefaultPosition,
			wxDefaultSize,
			array(),
			wxLB_SINGLE | wxLB_ALWAYS_SB | wxLB_SORT
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxlistbox_main_window_modules,
			1,
			wxEXPAND
		);
		
		// A static text + a listbox for javascript of a website project.
		$this->wxstatictext_main_window_javascript = new wxStaticText(
			$this->panel_main_window,
			WXID_WXSTATICTEXT_MAIN_WINDOW_JAVASCRIPT,
			TEXT_WXSTATICTEXT_MAIN_WINDOW_JAVASCRIPT
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxstatictext_main_window_javascript,
			0
		);
		$this->wxlistbox_main_window_javascript = new wxListBox(
			$this->panel_main_window,
			WXID_WXLISTBOX_MAIN_WINDOW_JAVSCRIPT,
			wxDefaultPosition,
			wxDefaultSize,
			array(),
			wxLB_SINGLE | wxLB_ALWAYS_SB | wxLB_SORT
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxlistbox_main_window_javascript,
			1,
			wxEXPAND
		);
		
		// A static text + a listbox for the CSS files of a website project.
		$this->wxstatictext_main_window_css = new wxStaticText(
			$this->panel_main_window,
			WXID_WXSTATICTEXT_MAIN_WINDOW_CSS,
			TEXT_WXSTATICTEXT_MAIN_WINDOW_CSS
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxstatictext_main_window_css,
			0
		);
		$this->wxlistbox_main_window_css = new wxListBox(
			$this->panel_main_window,
			WXID_WXLISTBOX_MAIN_WINDOW_JAVASCRIPT,
			wxDefaultPosition,
			wxDefaultSize,
			array(),
			wxLB_SINGLE | wxLB_ALWAYS_SB | wxLB_SORT
		);
		$this->vbox_main_window_other_controls->Add(
			$this->wxlistbox_main_window_css,
			1,
			wxEXPAND
		);

		// The vertical box is contained inside the horizontal box.
		$this->hbox_main_window_controls->Add(
			$this->vbox_main_window_other_controls,
			1,
			wxEXPAND
		);


		/* A second vertical box contains the edit area (textcontrol with
		multiple lines) and a single button to apply (save) the changes to the
		file being edited. */
		$this->vbox_main_window_edit_controls = new wxBoxSizer( wxVERTICAL );

		/* A static text + the textcontrol with multiple lines + a button to
		save the changes. */
		
		$this->wxstatictext_main_window_editor = new wxStaticText(
			$this->panel_main_window,
			WXID_WXSTATICTEXT_MAIN_WINDOW_EDITOR,
			TEXT_WXSTATICTEXT_MAIN_WINDOW_EDITOR
		);
		$this->vbox_main_window_edit_controls->Add(
			$this->wxstatictext_main_window_editor,
			0
		);

		// The styled editor.
		$this->wxtextctrl_main_window_editor = new wxStyledTextCtrl(
			$this->panel_main_window,
			WXID_WXTEXTCTRL_MAIN_WINDOW_EDITOR,
			wxDefaultPosition,
			wxDefaultSize
		);
		$this->wxtextctrl_main_window_editor->StyleClearAll();

		$font1 = new wxFont( 11, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL,
							 wxFONTWEIGHT_NORMAL );

		$this->wxtextctrl_main_window_editor->StyleSetFont( wxSTC_STYLE_DEFAULT, $font1 );	

		$this->wxtextctrl_main_window_editor->SetMarginWidth( 0, 50 );
		$this->wxtextctrl_main_window_editor->SetMarginType( 0, wxSTC_MARGIN_NUMBER );
		$this->wxtextctrl_main_window_editor->SetWrapMode( wxSTC_WRAP_WORD );		
		$this->wxtextctrl_main_window_editor->SetStyleBits( 7 );
		$this->wxtextctrl_main_window_editor->SetLexer( wxSTC_LEX_PHPSCRIPT );	
		
		$this->wxtextctrl_main_window_editor->StyleSetForeground( wxSTC_HPHP_DEFAULT, new wxColour( wxBLACK ) );
		$this->wxtextctrl_main_window_editor->StyleSetForeground( wxSTC_HPHP_HSTRING, new wxColour( wxRED ) );
		$this->wxtextctrl_main_window_editor->StyleSetForeground( wxSTC_HPHP_SIMPLESTRING, new wxColour( wxRED ) );
		$this->wxtextctrl_main_window_editor->StyleSetForeground( wxSTC_HPHP_WORD, new wxColour( wxYELLOW ) );
		$this->wxtextctrl_main_window_editor->StyleSetForeground( wxSTC_HPHP_NUMBER, new wxColour( wxBLUE ) );
		$this->wxtextctrl_main_window_editor->StyleSetForeground( wxSTC_HPHP_VARIABLE, new wxColour( 200, 0, 200 ) );
		$this->wxtextctrl_main_window_editor->StyleSetForeground( wxSTC_HPHP_COMMENT, new wxColour( wxLIGHT_GREY ) );
		$this->wxtextctrl_main_window_editor->StyleSetForeground( wxSTC_HPHP_COMMENTLINE, new wxColour( wxLIGHT_GREY ) );
		$this->wxtextctrl_main_window_editor->StyleSetForeground( wxSTC_HPHP_HSTRING_VARIABLE, new wxColour( wxCYAN ) );
		$this->wxtextctrl_main_window_editor->StyleSetForeground( wxSTC_HPHP_OPERATOR, new wxColour( 120, 120, 0 ) );

		$this->vbox_main_window_edit_controls->Add(
			$this->wxtextctrl_main_window_editor,
			1,
			wxEXPAND
		);
		$this->wxbutton_main_window_save = new wxButton(
			$this->panel_main_window,
			WXID_WXBUTTON_MAIN_WINDOW_SAVE,
			TEXT_WXBUTTON_MAIN_WINDOW_SAVE
		);
		$this->vbox_main_window_edit_controls->Add(
			$this->wxbutton_main_window_save,
			0
		);

		// Add the second vertical box to the hbox.
		$this->hbox_main_window_controls->Add(
			$this->vbox_main_window_edit_controls,
			5,
			wxEXPAND
		);


		/***********************************************************************
		A vertical box on the right contains controls related to media and
		files.
		***********************************************************************/
		$this->vbox_main_window_media_download_controls = new wxBoxSizer( wxVERTICAL );

		// A static text displays the media heading.
		$this->wxstatictext_main_window_media = new wxStaticText(
			$this->panel_main_window,
			WXID_WXSTATICTEXT_MAIN_WINDOW_MEDIA,
			TEXT_WXSTATICTEXT_MAIN_WINDOW_MEDIA
		);
		$this->vbox_main_window_media_download_controls->Add(
			$this->wxstatictext_main_window_media,
			0,
			wxEXPAND
		);

		/* A wxDataViewTreeCtrl widget displays the tree with the various media
		files and directories. */
		$this->wxdataviewtreectrl_main_window_media = new wxDataViewTreeCtrl(
			$this->panel_main_window,
			WXID_WXDATAVIEWTREECTRL_MAIN_WINDOW_MEDIA
		);	
		$this->vbox_main_window_media_download_controls->Add(
			$this->wxdataviewtreectrl_main_window_media,
			1,
			wxEXPAND
		);

		// A static text widget displays the downloads heading.
		$this->wxstatictext_main_window_downloads = new wxStaticText(
			$this->panel_main_window,
			WXID_WXSTATICTEXT_MAIN_WINDOW_DOWNLOADS,
			TEXT_WXSTATICTEXT_MAIN_WINDOW_DOWNLOADS
		);
		$this->vbox_main_window_media_download_controls->Add(
			$this->wxstatictext_main_window_downloads,
			0,
			wxEXPAND
		);

		/* A wxDataViewTreeCtrl widget displays the tree with the various
		download files and directories. */
		$this->wxdataviewtreectrl_main_window_downloads = new wxDataViewTreeCtrl(
			$this->panel_main_window,
			WXID_WXDATAVIEWTREECTRL_MAIN_WINDOW_DOWNLOADS
		);
		$this->vbox_main_window_media_download_controls->Add(
			$this->wxdataviewtreectrl_main_window_downloads,
			1,
			wxEXPAND
		);

		// The wxwidgets will appear on the right of the main window.
		$this->hbox_main_window_controls->Add(
			$this->vbox_main_window_media_download_controls,
			1,
			wxEXPAND
		);

		// Make sure all controls are visible.
		$this->panel_main_window->SetSizer( $this->hbox_main_window_controls );
		$this->hbox_main_window_controls->SetSizeHints( $this );



		/* The main window has now been set up.  Now it is time to set up the
		dialogs for all the various actions that can occur. */
		//
		// The dialog for managing templates.
		//
		$this->wxdialog_manage_templates = new wxDialog(
			$this,
			WXID_WXDIALOG_MANAGE_TEMPLATES,
			TEXT_WXDIALOG_MANAGE_TEMPLATES,
			wxDefaultPosition,
			wxDefaultSize,
			wxDEFAULT_DIALOG_STYLE
		);

		// We need a panel for our multiple controls.
		$this->wxpanel_manage_templates = new wxPanel(
			$this->wxdialog_manage_templates,
			wxID_ANY
		);

		/* We need a horizontal box and two vertical boxes.  The left vertical
		box is going to contain a wxListBox control, which shows which templates
		exist.  The right vertical box is going to contain several buttons, each
		of which opens a new dialog window, through which the user can do
		something. */
		$this->hbox_manage_templates = new wxBoxSizer( wxHORIZONTAL );
		$this->vbox_manage_templates_left = new wxBoxSizer( wxVERTICAL );
		$this->vbox_manage_templates_right = new wxBoxSizer( wxVERTICAL );

		// The left vertical box contains a wxListBox control.
		$this->wxlistbox_manage_templates = new wxListBox(
			$this->wxpanel_manage_templates,
			WXID_WXLISTBOX_MANAGE_TEMPLATES,
			wxDefaultPosition,
			wxDefaultSize,
			array(),
			wxLB_SINGLE | wxLB_ALWAYS_SB | wxLB_SORT
		);
		$this->vbox_manage_templates_left->Add(
			$this->wxlistbox_manage_templates,
			1,
			wxEXPAND,
			0
		);

		/* The right vertical box contains the buttons to manage each of the
		// templates shown in the wxListBox control. */

		// A button to add a new template.
		$this->wxbutton_manage_templates_add_template = new wxButton(
			$this->wxpanel_manage_templates,
			WXID_WXBUTTON_MANAGE_TEMPLATES_ADD_TEMPLATE,
			TEXT_WXBUTTON_MANAGE_TEMPLATES_ADD_TEMPLATE
		);
		$this->vbox_manage_templates_right->Add(
			$this->wxbutton_manage_templates_add_template,
			1,
			wxEXPAND,
			0
		);

		// A button to rename an existing template.
		$this->wxbutton_manage_templates_rename_template = new wxButton(
			$this->wxpanel_manage_templates,
			WXID_WXBUTTON_MANAGE_TEMPLATES_RENAME_TEMPLATE,
			TEXT_WXBUTTON_MANAGE_TEMPLATES_RENAME_TEMPLATE
		);
		$this->vbox_manage_templates_right->Add(
			$this->wxbutton_manage_templates_rename_template,
			1,
			wxEXPAND,
			0
		);
		/* This button is deactivated at the beginning by default, because no
		template has yet been selected. */
		$this->wxbutton_manage_templates_rename_template->Disable();

		// A button to delete an existing template.
		$this->wxbutton_manage_templates_delete_template = new wxButton(
			$this->wxpanel_manage_templates,
			WXID_WXBUTTON_MANAGE_TEMPLATES_DELETE_TEMPLATE,
			TEXT_WXBUTTON_MANAGE_TEMPLATES_DELETE_TEMPLATE
		);
		$this->vbox_manage_templates_right->Add(
			$this->wxbutton_manage_templates_delete_template,
			1,
			wxEXPAND,
			0
		);
		/* This button is deactivated at the beginning by default, because no
		template has yet been selected. */
		$this->wxbutton_manage_templates_delete_template->Disable();
		
			
		$this->hbox_manage_templates->Add(
			$this->vbox_manage_templates_left,
			1,
			wxEXPAND
		);
		$this->hbox_manage_templates->Add(
			$this->vbox_manage_templates_right,
			1,
			wxEXPAND
		);

		$this->wxpanel_manage_templates->SetSizer( $this->hbox_manage_templates );
		$this->hbox_manage_templates->SetSizeHints( $this->wxdialog_manage_templates );

		//
		// The dialog for managing modules.
		//
		$this->wxdialog_manage_modules = new wxDialog(
			$this,
			WXID_WXDIALOG_MANAGE_MODULES,
			TEXT_WXDIALOG_MANAGE_MODULES
		);

		// We require a panel for all of our controls.
		$this->wxpanel_manage_modules = new wxPanel(
			$this->wxdialog_manage_modules,
			wxID_ANY
		);

		/* We will use one horizontal box and two vertical boxes for laying out
		our controls.  The wxListBox control will go into the left vertical box,
		the other controls (wxButton) will go into the right vertical box. */
		$this->hbox_manage_modules = new wxBoxSizer( wxHORIZONTAL );
		$this->vbox_manage_modules_left = new wxBoxSizer( wxVERTICAL );
		$this->vbox_manage_modules_right = new wxBoxSizer( wxVERTICAL );

		// We need a wxListBox control to display all of the available modules.
		$this->wxlistbox_manage_modules = new wxListBox(
			$this->wxpanel_manage_modules,
			WXID_WXLISTBOX_MANAGE_MODULES,
			wxDefaultPosition,
			wxDefaultSize,
			array(),
			wxLB_SINGLE | wxLB_ALWAYS_SB | wxLB_SORT
		);
		$this->vbox_manage_modules_left->Add(
			$this->wxlistbox_manage_modules,
			1,
			wxEXPAND,
			0
		);

		/* The buttons to add, rename and delete a module go into the right
		vertical box. */
		$this->wxbutton_manage_modules_add_module = new wxButton(
			$this->wxpanel_manage_modules,
			WXID_WXBUTTON_MANAGE_MODULES_ADD_MODULE,
			TEXT_WXBUTTON_MANAGE_MODULES_ADD_MODULE
		);
		$this->vbox_manage_modules_right->Add(
			$this->wxbutton_manage_modules_add_module,
			1,
			wxEXPAND,
			0
		);

		$this->wxbutton_manage_modules_rename_module = new wxButton(
			$this->wxpanel_manage_modules,
			WXID_WXBUTTON_MANAGE_MODULES_RENAME_MODULE,
			TEXT_WXBUTTON_MANAGE_MODULES_RENAME_MODULE
		);
		$this->vbox_manage_modules_right->Add(
			$this->wxbutton_manage_modules_rename_module,
			1,
			wxEXPAND,
			0
		);
		// This button needs to be deactivated by default at the beginning.
		$this->wxbutton_manage_modules_rename_module->Disable();		

		$this->wxbutton_manage_modules_delete_module = new wxButton(
			$this->wxpanel_manage_modules,
			WXID_WXBUTTON_MANAGE_MODULES_DELETE_MODULE,
			TEXT_WXBUTTON_MANAGE_MODULES_DELETE_MODULE
		);
		$this->vbox_manage_modules_right->Add(
			$this->wxbutton_manage_modules_delete_module,
			1,
			wxEXPAND,
			0
		);
		// This button needs to be deactivated by default at the beginning.
		$this->wxbutton_manage_modules_delete_module->Disable();		
		
		// Add our vertical boxes to the horizontal box.
		$this->hbox_manage_modules->Add(
			$this->vbox_manage_modules_left,
			1,
			wxEXPAND
		);
		$this->hbox_manage_modules->Add(
			$this->vbox_manage_modules_right,
			1,
			wxEXPAND
		);

		// Fit all of our controls into the dialog.
		$this->wxpanel_manage_modules->SetSizer( $this->hbox_manage_modules );
		$this->hbox_manage_modules->SetSizeHints( $this->wxdialog_manage_modules );


		//
		// The dialog for managing JavaScript files.
		//
		$this->wxdialog_manage_javascript = new wxDialog(
			$this,
			WXID_WXDIALOG_MANAGE_JAVASCRIPT,
			TEXT_WXDIALOG_MANAGE_JAVASCRIPT
		);
		
		// We need a panel to put our controls into.
		$this->wxpanel_manage_javascript = new wxPanel(
			$this->wxdialog_manage_javascript,
			wxID_ANY
		);

		/* We need one horizontal and two vertical boxes where we can put our
		controls into.  The left vertical box will contain a wxListBox control,
		where as the right vertical box will contain the buttons to add, rename
		and delete a javacript file. */
		$this->wxhbox_manage_javascript = new wxBoxSizer( wxHORIZONTAL );
		$this->wxvbox_manage_javascript_left = new wxBoxSizer( wxVERTICAL );
		$this->wxvbox_manage_javascript_right = new wxBoxSizer( wxVERTICAL );

		// Now let us create a wxListBox that lists all of our javascript files.
		$this->wxlistbox_manage_javascript = new wxListBox(
			$this->wxpanel_manage_javascript,
			WXID_WXLISTBOX_MANAGE_JAVASCRIPT,
			wxDefaultPosition,
			wxDefaultSize,
			array(),
			wxLB_SINGLE | wxLB_ALWAYS_SB | wxLB_SORT
		);
		$this->wxvbox_manage_javascript_left->Add(
			$this->wxlistbox_manage_javascript,
			1,
			wxEXPAND,
			0
		);

		/* Now let us add the three buttons to add, rename and delete javascript
		files. */
		$this->wxbutton_manage_javascript_add_javascript = new wxButton(
			$this->wxpanel_manage_javascript,
			WXID_WXBUTTON_MANAGE_JAVASCRIPT_ADD_JAVASCRIPT,
			TEXT_WXBUTTON_MANAGE_JAVASCRIPT_ADD_JAVASCRIPT
		);
		$this->wxvbox_manage_javascript_right->Add(
			$this->wxbutton_manage_javascript_add_javascript,
			1,
			wxEXPAND
		);

		$this->wxbutton_manage_javascript_rename_javascript = new wxButton(
			$this->wxpanel_manage_javascript,
			WXID_WXBUTTON_MANAGE_JAVASCRIPT_RENAME_JAVASCRIPT,
			TEXT_WXBUTTON_MANAGE_JAVASCRIPT_RENAME_JAVASCRIPT
		);
		$this->wxvbox_manage_javascript_right->Add(
			$this->wxbutton_manage_javascript_rename_javascript,
			1,
			wxEXPAND
		);
		// This button is diabled by default at the beginning.
		$this->wxbutton_manage_javascript_rename_javascript->Disable();

		$this->wxbutton_manage_javascript_delete_javascript = new wxButton(
			$this->wxpanel_manage_javascript,
			WXID_WXBUTTON_MANAGE_JAVASCRIPT_DELETE_JAVASCRIPT,
			TEXT_WXBUTTON_MANAGE_JAVASCRIPT_DELETE_JAVASCRIPT
		);
		$this->wxvbox_manage_javascript_right->Add(
			$this->wxbutton_manage_javascript_delete_javascript,
			1,
			wxEXPAND
		);
		// This button is disabled by default at the beginning.
		$this->wxbutton_manage_javascript_delete_javascript->Disable();
		

		// The two vertical boxes go into the horizontal box.
		$this->wxhbox_manage_javascript->Add(
			$this->wxvbox_manage_javascript_left,
			1,
			wxEXPAND
		);
		$this->wxhbox_manage_javascript->Add(
			$this->wxvbox_manage_javascript_right,
			1,
			wxEXPAND
		);

		// Fit all of the controls into the dialog.
		$this->wxpanel_manage_javascript->SetSizer( $this->wxhbox_manage_javascript );
		$this->wxhbox_manage_javascript->SetSizeHints( $this->wxdialog_manage_javascript );

		//
		// The dialog for managing CSS files.
		//
		$this->wxdialog_manage_css = new wxDialog(
			$this,
			WXID_WXDIALOG_MANAGE_CSS,
			TEXT_WXDIALOG_MANAGE_CSS
		);

		// All controls are contained inside a panel.
		$this->wxpanel_manage_css = new wxPanel(
			$this->wxdialog_manage_css,
			wxID_ANY
		);

		// Again we are going to need one horizontal box and 2 vertical boxes.
		/* The left vertical box is going to contain a wxListBox control which
		contains a list of all css files.
		The right vertical box contains three buttons to add, rename and delete
		CSS files. */
		$this->wxhbox_manage_css = new wxBoxSizer( wxHORIZONTAL );
		$this->wxvbox_manage_css_left = new wxBoxSizer( wxVERTICAL );
		$this->wxvbox_manage_css_right = new wxBoxSizer( wxVERTICAL );
		
		
		// First of all, create another wxListBox control which lists all css files.
		$this->wxlistbox_manage_css = new wxListBox(
			$this->wxpanel_manage_css,
			WXID_WXLISTBOX_MANAGE_CSS,
			wxDefaultPosition,
			wxDefaultSize,
			array(),
			wxLB_ALWAYS_SB | wxLB_SINGLE | wxLB_SORT
		);		
		$this->wxvbox_manage_css_left->Add(
			$this->wxlistbox_manage_css,
			1,
			wxEXPAND
		);

		// Now create the three buttons to add, rename and delete css files.
		$this->wxbutton_manage_css_add_css = new wxButton(
			$this->wxpanel_manage_css,
			WXID_WXBUTTON_MANAGE_CSS_ADD_CSS,
			TEXT_WXBUTTON_MANAGE_CSS_ADD_CSS
		);
		$this->wxvbox_manage_css_right->Add(
			$this->wxbutton_manage_css_add_css,
			1,
			wxEXPAND
		);

		$this->wxbutton_manage_css_rename_css = new wxButton(
			$this->wxpanel_manage_css,
			WXID_WXBUTTON_MANAGE_CSS_RENAME_CSS,
			TEXT_WXBUTTON_MANAGE_CSS_RENAME_CSS
		);
		$this->wxvbox_manage_css_right->Add(
			$this->wxbutton_manage_css_rename_css,
			1,
			wxEXPAND
		);
		// By default, this button is disabled.		
		$this->wxbutton_manage_css_rename_css->Disable();		

		$this->wxbutton_manage_css_delete_css = new wxButton(
			$this->wxpanel_manage_css,
			WXID_WXBUTTON_MANAGE_CSS_DELETE_CSS,
			TEXT_WXBUTTON_MANAGE_CSS_DELETE_CSS
		);
		$this->wxvbox_manage_css_right->Add(
			$this->wxbutton_manage_css_delete_css,
			1,
			wxEXPAND
		);
		// By default, this button is disabled.
		$this->wxbutton_manage_css_delete_css->Disable();

		// The horizontal box contains the two vertical boxes.
		$this->wxhbox_manage_css->Add(
			$this->wxvbox_manage_css_left,
			1,
			wxEXPAND
		);
		$this->wxhbox_manage_css->Add(
			$this->wxvbox_manage_css_right,
			1,
			wxEXPAND
		);

		// Fit all of the controls into the dialog.
		$this->wxpanel_manage_css->SetSizer( $this->wxhbox_manage_css );
		$this->wxhbox_manage_css->SetSizeHints( $this->wxdialog_manage_css );


		//
		// The dialog for managing the website structure.
		//
		$this->wxdialog_manage_website_structure = new wxDialog(
			$this,
			WXID_WXDIALOG_MANAGE_WEBSITE_STRUCTURE,
			TEXT_WXDIALOG_MANAGE_WEBSITE_STRUCTURE
		);

		// We need a panel for our controls.
		$this->wxpanel_manage_website_structure = new wxPanel(
			$this->wxdialog_manage_website_structure,
			wxID_ANY
		);

		/* We are going to create one horizontal box and two vertical boxes for
		our controls.
		The left vertical box is going to contain a wxTreeCtrl item and two
		static text widgets, that show which template a selected page uses,
		where as the right vertical box contains the buttons to alter the
		website structure.
		*/
		$this->wxhbox_manage_website_structure = new wxBoxSizer( wxHORIZONTAL );
		$this->wxvbox_manage_website_structure_left = new wxBoxSizer( wxVERTICAL );
		$this->wxvbox_manage_website_structure_right = new wxBoxSizer( wxVERTICAL );

		// The website structure is displayed by using a wxTreeCtrl control.
		$this->wxtreectrl_manage_website_structure = new wxTreeCtrl(
			$this->wxpanel_manage_website_structure,
			WXID_WXTREECTRL_MANAGE_WEBSITE_STRUCTURE,
			wxDefaultPosition,
			wxDefaultSize,
			wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT
		);
		// TEMPORARY ONLY.
		// Collapse the entire tree.
		$this->wxtreectrl_manage_website_structure->ExpandAll();
						
		$this->wxvbox_manage_website_structure_left->Add(
			$this->wxtreectrl_manage_website_structure,
			1,
			wxEXPAND
		);	
		/* Two static text widgets that display information about the template
		being used for a selected page. */
		$this->wxstatictext_manage_website_structure_template_used_caption = new wxStaticText(
			$this->wxpanel_manage_website_structure,
			WXID_WXSTATICTEXT_MANAGE_WEBSITE_STRUCTURE_TEMPLATE_USED_CAPTION,
			TEXT_WXSTATICTEXT_MANAGE_WEBSITE_STRUCTURE_TEMPLATE_USED_CAPTION
		);
		$this->wxvbox_manage_website_structure_left->Add(
			$this->wxstatictext_manage_website_structure_template_used_caption,
			0,
			wxEXPAND
		);
		$this->wxstatictext_manage_website_structure_template_used = new wxStaticText(
			$this->wxpanel_manage_website_structure,
			WXID_WXSTATICTEXT_MANAGE_WEBSITE_STRUCTURE_TEMPLATE_USED,
			TEXT_WXSTATICTEXT_MANAGE_WEBSITE_STRUCTURE_TEMPLATE_USED
		);
		$this->wxvbox_manage_website_structure_left->Add(
			$this->wxstatictext_manage_website_structure_template_used,
			0,
			wxEXPAND
		);

		/* I need buttons to add, rename, delete, move up, move down and move
		items. */
		$this->wxbutton_manage_website_structure_add_item = new wxButton(
			$this->wxpanel_manage_website_structure,
			WXID_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_ADD_ITEM,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_ADD_ITEM
		);
		$this->wxvbox_manage_website_structure_right->Add(
			$this->wxbutton_manage_website_structure_add_item,
			1,
			wxEXPAND
		);

		$this->wxbutton_manage_website_structure_rename_item = new wxButton(
			$this->wxpanel_manage_website_structure,
			WXID_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_RENAME_ITEM,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_RENAME_ITEM
		);
		$this->wxvbox_manage_website_structure_right->Add(
			$this->wxbutton_manage_website_structure_rename_item,
			1,
			wxEXPAND
		);
		// This button is disabled by default.
		$this->wxbutton_manage_website_structure_rename_item->Disable();

		$this->wxbutton_manage_website_structure_delete_item = new wxButton(
			$this->wxpanel_manage_website_structure,
			WXID_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_DELETE_ITEM,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_DELETE_ITEM
		);
		$this->wxvbox_manage_website_structure_right->Add(
			$this->wxbutton_manage_website_structure_delete_item,
			1,
			wxEXPAND
		);
		// This button is disabled by default.
		$this->wxbutton_manage_website_structure_delete_item->Disable();		

		$this->wxbutton_manage_website_structure_move_up_item = new wxButton(
			$this->wxpanel_manage_website_structure,
			WXID_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_MOVE_UP_ITEM,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_MOVE_UP_ITEM
		);
		$this->wxvbox_manage_website_structure_right->Add(
			$this->wxbutton_manage_website_structure_move_up_item,
			1,
			wxEXPAND
		);
		// This button is disabled by default.
		$this->wxbutton_manage_website_structure_move_up_item->Disable();		

		$this->wxbutton_manage_website_structure_move_down_item = new wxButton(
			$this->wxpanel_manage_website_structure,
			WXID_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_MOVE_DOWN_ITEM,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_MOVE_DOWN_ITEM
		);
		$this->wxvbox_manage_website_structure_right->Add(
			$this->wxbutton_manage_website_structure_move_down_item,
			1,
			wxEXPAND
		);
		// This button is disabled by default.
		$this->wxbutton_manage_website_structure_move_down_item->Disable();		

		$this->wxbutton_manage_website_structure_relocate_itemtree = new wxButton(
			$this->wxpanel_manage_website_structure,
			WXID_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_RELOCATE_ITEMTREE,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_RELOCATE_ITEMTREE
		);
		$this->wxvbox_manage_website_structure_right->Add(
			$this->wxbutton_manage_website_structure_relocate_itemtree,
			1,
			wxEXPAND
		);
		// This button is disabled by default.
		$this->wxbutton_manage_website_structure_relocate_itemtree->Disable();

		// A button to change the template of a selected item.
		$this->wxbutton_manage_website_structure_change_template = new wxButton(
			$this->wxpanel_manage_website_structure,
			WXID_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_CHANGE_TEMPLATE,
			TEXT_WXBUTTON_MANAGE_WEBSITE_STRUCTURE_CHANGE_TEMPLATE
		);
		$this->wxvbox_manage_website_structure_right->Add(
			$this->wxbutton_manage_website_structure_change_template,
			1,
			wxEXPAND
		);
		// This button is disabled by default.
		$this->wxbutton_manage_website_structure_change_template->Disable();



		$this->wxhbox_manage_website_structure->Add(
			$this->wxvbox_manage_website_structure_left,
			1,
			wxEXPAND
		);
		$this->wxhbox_manage_website_structure->Add(
			$this->wxvbox_manage_website_structure_right,
			1,
			wxEXPAND
		);

		// Fit all of the controls into the dialog.
		$this->wxpanel_manage_website_structure->SetSizer(
			$this->wxhbox_manage_website_structure
		);
		$this->wxhbox_manage_website_structure->SetSizeHints(
			$this->wxdialog_manage_website_structure
		);

		//
		// Dialog for managing media:
		//
		$this->wxdialog_manage_media = new wxDialog(
			$this,
			WXID_WXDIALOG_MANAGE_MEDIA,
			TEXT_WXDIALOG_MANAGE_MEDIA
		);

		$this->wxpanel_manage_media = new wxPanel(
			$this->wxdialog_manage_media
		);

		$this->wxhbox_manage_media = new wxBoxSizer( wxHORIZONTAL );
		$this->wxvbox_left_manage_media = new wxBoxSizer( wxVERTICAL );
		$this->wxvbox_right_manage_media = new wxBoxSizer( wxVERTICAL );

		$this->wxdataviewtreectrl_manage_media = new wxDataViewTreeCtrl(
			$this->wxpanel_manage_media,
			WXID_WXDATAVIEWTREECTRL_MANAGE_MEDIA
		);

		$this->wxvbox_left_manage_media->Add(
			$this->wxdataviewtreectrl_manage_media,
			1,
			wxEXPAND
		);

		$this->wxbutton_add_file_manage_media = new wxButton(
			$this->wxpanel_manage_media,
			WXID_WXBUTTON_MANAGE_MEDIA_ADD_FILE,
			TEXT_WXBUTTON_WXDIALOG_MANAGE_MEDIA_ADD_FILE
		);
		$this->wxvbox_right_manage_media->Add(
			$this->wxbutton_add_file_manage_media,
			1,
			wxEXPAND
		);

		$this->wxbutton_rename_manage_media = new wxButton(
			$this->wxpanel_manage_media,
			WXID_WXBUTTON_MANAGE_MEDIA_RENAME,
			TEXT_WXBUTTON_WXDIALOG_MANAGE_MEDIA_RENAME
		);
		$this->wxbutton_rename_manage_media->Enable( FALSE );
		$this->wxvbox_right_manage_media->Add(
			$this->wxbutton_rename_manage_media,
			1,
			wxEXPAND
		);

		$this->wxbutton_delete_manage_media = new wxButton(
			$this->wxpanel_manage_media,
			WXID_WXBUTTON_MANAGE_MEDIA_DELETE,
			TEXT_WXBUTTON_WXDIALOG_MANAGE_MEDIA_DELETE
		);
		$this->wxbutton_delete_manage_media->Enable( FALSE );
		$this->wxvbox_right_manage_media->Add(
			$this->wxbutton_delete_manage_media,
			1,
			wxEXPAND
		);

		$this->wxbutton_add_directory_manage_media = new wxButton(
			$this->wxpanel_manage_media,
			WXID_WXBUTTON_MANAGE_MEDIA_ADD_DIRECTORY,
			TEXT_WXBUTTON_WXDIALOG_MANAGE_MEDIA_ADD_DIRECTORY
		);
		$this->wxvbox_right_manage_media->Add(
			$this->wxbutton_add_directory_manage_media,
			1,
			wxEXPAND
		);

		$this->wxhbox_manage_media->Add(
			$this->wxvbox_left_manage_media,
			1,
			wxEXPAND
		);
		$this->wxhbox_manage_media->Add(
			$this->wxvbox_right_manage_media,
			1,
			wxEXPAND
		);

		// Fit all of the controls into the dialog.
		$this->wxpanel_manage_media->SetSizer( $this->wxhbox_manage_media );
		$this->wxhbox_manage_media->SetSizeHints( $this->wxdialog_manage_media );


		//
		// Dialog for managing downloads.
		//
		$this->wxdialog_manage_downloads = new wxDialog(
			$this,
			WXID_WXDIALOG_MANAGE_DOWNLOADS,
			TEXT_WXDIALOG_MANAGE_DOWNLOADS
		);

		$this->wxpanel_manage_downloads = new wxPanel(
			$this->wxdialog_manage_downloads
		);

		$this->wxhbox_manage_downloads = new wxBoxSizer( wxHORIZONTAL );
		$this->wxvbox_left_manage_downloads = new wxBoxSizer( wxVERTICAL );
		$this->wxvbox_right_manage_downloads = new wxBoxSizer( wxVERTICAL );

		$this->wxdataviewtreectrl_manage_downloads = new wxDataViewTreeCtrl(
			$this->wxpanel_manage_downloads,
			WXID_WXDATAVIEWTREECTRL_MANAGE_DOWNLOADS
		);

		$this->wxvbox_left_manage_downloads->Add(
			$this->wxdataviewtreectrl_manage_downloads,
			1,
			wxEXPAND
		);

		$this->wxbutton_add_file_manage_downloads = new wxButton(
			$this->wxpanel_manage_downloads,
			WXID_WXBUTTON_MANAGE_DOWNLOADS_ADD_FILE,
			TEXT_WXBUTTON_WXDIALOG_MANAGE_DOWNLOADS_ADD_FILE
		);
		$this->wxvbox_right_manage_downloads->Add(
			$this->wxbutton_add_file_manage_downloads,
			1,
			wxEXPAND
		);

		$this->wxbutton_rename_manage_downloads = new wxButton(
			$this->wxpanel_manage_downloads,
			WXID_WXBUTTON_MANAGE_DOWNLOADS_RENAME,
			TEXT_WXBUTTON_WXDIALOG_MANAGE_DOWNLOADS_RENAME
		);
		$this->wxvbox_right_manage_downloads->Add(
			$this->wxbutton_rename_manage_downloads,
			1,
			wxEXPAND
		);

		$this->wxbutton_delete_manage_downloads = new wxButton(
			$this->wxpanel_manage_downloads,
			WXID_WXBUTTON_MANAGE_DOWNLOADS_DELETE,
			TEXT_WXBUTTON_WXDIALOG_MANAGE_DOWNLOADS_DELETE
		);
		$this->wxbutton_delete_manage_downloads->Enable( FALSE );
		$this->wxvbox_right_manage_downloads->Add(
			$this->wxbutton_delete_manage_downloads,
			1,
			wxEXPAND
		);

		$this->wxbutton_add_directory_manage_downloads = new wxButton(
			$this->wxpanel_manage_downloads,
			WXID_WXBUTTON_MANAGE_DOWNLOADS_ADD_DIRECTORY,
			TEXT_WXBUTTON_WXDIALOG_MANAGE_DOWNLOADS_ADD_DIRECTORY
		);
		$this->wxvbox_right_manage_downloads->Add(
			$this->wxbutton_add_directory_manage_downloads,
			1,
			wxEXPAND
		);

		$this->wxhbox_manage_downloads->Add(
			$this->wxvbox_left_manage_downloads,
			1,
			wxEXPAND
		);
		$this->wxhbox_manage_downloads->Add(
			$this->wxvbox_right_manage_downloads,
			1,
			wxEXPAND
		);

		// Fit all of the controls into the dialog.
		$this->wxpanel_manage_downloads->SetSizer( $this->wxhbox_manage_downloads );
		$this->wxhbox_manage_downloads->SetSizeHints( $this->wxdialog_manage_downloads );


		

		//
		// All eventhandlers are listed here.
		//
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_FILE_NEW_PROJECT,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_file_new_project"
			)
		);
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_FILE_OPEN_PROJECT,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_file_open_project"
			)
		);
		$this->Connect(
			wxID_EXIT,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_file_exit"
			)
		);
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_TEMPLATES,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_project_manage_templates"
			)
		);
		
		// Manage templates.		
		$this->wxlistbox_manage_templates->Connect(
			wxEVT_COMMAND_LISTBOX_SELECTED,
			array(
				$this,
				"on_wxlistbox_manage_templates_selection"
			)
		);
		$this->wxbutton_manage_templates_add_template->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_templates_add_template_button_click"
			)
		);
		$this->wxbutton_manage_templates_rename_template->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_templates_rename_template_button_click"
			)
		);
		$this->wxbutton_manage_templates_delete_template->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_templates_delete_template_button_click"
			)
		);
		// Manage modules.
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_MODULES,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_project_manage_modules"
			)
		);
		$this->wxlistbox_manage_modules->Connect(
			wxEVT_COMMAND_LISTBOX_SELECTED,
			array(
				$this,
				"on_wxlistbox_manage_modules_selection"
			)
		);
		$this->wxbutton_manage_modules_add_module->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_modules_add_module_button_click"
			)
		);
		
		$this->wxbutton_manage_modules_rename_module->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_modules_rename_module_button_click"
			)
		);
				
		$this->wxbutton_manage_modules_delete_module->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_modules_delete_module_button_click"
			)
		);
		// Manage javascript.
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_JAVASCRIPT,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_project_manage_javascript"
			)
		);
		$this->wxlistbox_manage_javascript->Connect(
			wxEVT_COMMAND_LISTBOX_SELECTED,
			array(
				$this,
				"on_wxlistbox_manage_javascript_selection"
			)
		);
		$this->wxbutton_manage_javascript_add_javascript->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_javascript_add_javascript_button_click"
			)
		);
		$this->wxbutton_manage_javascript_rename_javascript->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_javascript_rename_javascript_button_click"
			)
		);
		$this->wxbutton_manage_javascript_delete_javascript->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_javascript_delete_javascript_button_click"
			)
		);
		// Eventhandlers for managing CSS files.
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_CSS,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_project_manage_css"
			)
		);
		$this->wxlistbox_manage_css->Connect(
			wxEVT_COMMAND_LISTBOX_SELECTED,
			array(
				$this,
				"on_wxlistbox_manage_css_selection"
			)
		);
		$this->wxbutton_manage_css_add_css->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_css_add_css_button_click"
			)
		);
		$this->wxbutton_manage_css_rename_css->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_css_rename_css_button_click"
			)
		);
		$this->wxbutton_manage_css_delete_css->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_css_delete_css_button_click"
			)
		);	
		// Manage media files.
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_MEDIA,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_project_manage_media"
			)
		);
		// Manage download files.
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_DOWNLOADS,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_project_manage_downloads"
			)
		);		
		// Generate the website.
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_PROJECT_GENERATEWEBSITE,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_project_generatewebsite"
			)
		);
		// Closing the project.
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_PROJECT_CLOSE,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_project_close"
			)
		);
		// Help
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_HELP_HELP,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_help_help"
			)
		);
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_HELP_ABOUT,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_help_about"
			)
		);
		// Manage the website structure.
		$this->Connect(
			WXID_MENU_MAIN_WINDOW_PROJECT_MANAGE_WEBSITE_STRUCTURE,
			wxEVT_COMMAND_MENU_SELECTED,
			array(
				$this,
				"on_menu_main_window_project_manage_website_structure"
			)
		);
		
		$this->wxtreectrl_manage_website_structure->Connect(
			wxEVT_TREE_SEL_CHANGED,
			array(
				$this,
				"on_wxtreectrl_manage_website_structure_selection"
			)
		);
		
		$this->wxtreectrl_manage_website_structure->Connect(
			wxEVT_TREE_ITEM_RIGHT_CLICK,
			array(
				$this,
				"on_wxtreectrl_manage_website_structure_selection"
			)
		);
		$this->wxbutton_manage_website_structure_add_item->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_website_structure_add_item_clicked"
			)
		);
		$this->wxbutton_manage_website_structure_rename_item->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_website_structure_rename_item_clicked"
			)
		);
		$this->wxbutton_manage_website_structure_delete_item->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_website_structure_delete_item_clicked"
			)
		);		
		$this->wxbutton_manage_website_structure_move_up_item->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_website_structure_move_up_item_clicked"
			)
		);
		$this->wxbutton_manage_website_structure_move_down_item->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_website_structure_move_down_item_clicked"
			)
		);
		$this->wxbutton_manage_website_structure_relocate_itemtree->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_website_structure_relocate_itemtree_clicked"
			)
		);
		$this->wxbutton_manage_website_structure_change_template->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_manage_website_structure_change_template_clicked"
			)
		);

		// Eventhandlers for the wxListCtrl widget in the main window.
		// For templates:
		$this->wxlistbox_main_window_templates->Connect(
			wxEVT_LISTBOX,
			array(
				$this,
				"on_wxlistbox_main_window_templates_click"
			)
		);

		/* Eventhandlers for the wxButton widget in the main window to write
		contents to a file. */
		$this->wxbutton_main_window_save->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_wxbutton_main_window_save"
			)
		);

		// Eventhandlers for the wxTreeCtrl widget in the main window.
		$this->wxtreectrl_main_window_website_structure->Connect(
			wxEVT_TREE_SEL_CHANGED,
			array(
				$this,
				"main_window_wxlistbox_containers_refresh_list"
			)
		);

		// Eventhandlers for the widgets in the main window.
		$this->wxlistbox_main_window_modules->Connect(
			wxEVT_LISTBOX,
			array(
				$this,
				"on_wxlistbox_main_window_modules_click"
			)
		);
		$this->wxlistbox_main_window_css->Connect(
			wxEVT_LISTBOX,
			array(
				$this,
				"on_wxlistbox_main_window_css_click"
			)
		);
		$this->wxlistbox_main_window_javascript->Connect(
			wxEVT_LISTBOX,
			array(
				$this,
				"on_wxlistbox_main_window_js_click"
			)
		);
		$this->wxlistbox_main_window_containers->Connect(
			wxEVT_LISTBOX,
			array(
				$this,
				"on_wxlistbox_main_window_containers_clicked"
			)
		);

		//
		// Eventhandlers for the manage media dialog.
		//
		$this->wxbutton_add_file_manage_media->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_menu_main_window_project_manage_media_add_file"
			)	
		);
		$this->wxbutton_rename_manage_media->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_menu_main_window_project_manage_media_rename"
			)
		);
		$this->wxbutton_add_directory_manage_media->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_manage_media_wxbutton_add_directory"
			)
		);
		$this->wxbutton_delete_manage_media->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_manage_media_wxbutton_delete"
			)
		);
		$this->wxdataviewtreectrl_manage_media->Connect(
			wxEVT_DATAVIEW_SELECTION_CHANGED,
			array(
				$this,
				"on_manage_media_wxdataviewtreectrl_selection_changed"
			)
		);
		$this->wxdataviewtreectrl_manage_media->Connect(
			wxEVT_DATAVIEW_ITEM_CONTEXT_MENU,
			array(
				$this,
				"on_manage_media_wxdataviewtreectrl_right_click"
			)
		);


		//
		// Eventhandlers for the manage downloads dialog.
		//
		$this->wxbutton_add_file_manage_downloads->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_menu_main_window_project_manage_downloads_add_file"
			)	
		);
		$this->wxbutton_rename_manage_downloads->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_menu_main_window_project_manage_downloads_rename"
			)
		);
		$this->wxbutton_add_directory_manage_downloads->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_manage_downloads_wxbutton_add_directory"
			)
		);
		$this->wxbutton_delete_manage_downloads->Connect(
			wxEVT_COMMAND_BUTTON_CLICKED,
			array(
				$this,
				"on_manage_downloads_wxbutton_delete"
			)
		);
		$this->wxdataviewtreectrl_manage_downloads->Connect(
			wxEVT_DATAVIEW_SELECTION_CHANGED,
			array(
				$this,
				"on_manage_downloads_wxdataviewtreectrl_selection_changed"
			)
		);
		$this->wxdataviewtreectrl_manage_downloads->Connect(
			wxEVT_DATAVIEW_ITEM_CONTEXT_MENU,
			array(
				$this,
				"on_manage_downloads_wxdataviewtreectrl_right_click"
			)
		);		
		

		// Refresh the list of website projects.
		$this->refresh_list_of_website_projects();
	}
}


class Dill extends wxApp
{
	function OnInit()
	{
		// Views.
		$this->gui = new GUI();
		// Show the GUI.
		$this->gui->Show();

		return 0;
	}

	function onExit()
	{
		return 0;
	}
}


// Run Dill.
$dill = new Dill();
wxApp::SetInstance( $dill );
wxEntry();

?>
